ESymSolverStatus MumpsSolverInterface::Solve(Index nrhs, double *rhs_vals) { DBG_START_METH("MumpsSolverInterface::Solve", dbg_verbosity); DMUMPS_STRUC_C* mumps_data = (DMUMPS_STRUC_C*)mumps_ptr_; ESymSolverStatus retval = SYMSOLVER_SUCCESS; if (HaveIpData()) { IpData().TimingStats().LinearSystemBackSolve().Start(); } for (Index i = 0; i < nrhs; i++) { Index offset = i * mumps_data->n; mumps_data->rhs = &(rhs_vals[offset]); mumps_data->job = 3;//solve Jnlst().Printf(J_MOREDETAILED, J_LINEAR_ALGEBRA, "Calling MUMPS-3 for solve at cpu time %10.3f (wall %10.3f).\n", CpuTime(), WallclockTime()); dmumps_c(mumps_data); Jnlst().Printf(J_MOREDETAILED, J_LINEAR_ALGEBRA, "Done with MUMPS-3 for solve at cpu time %10.3f (wall %10.3f).\n", CpuTime(), WallclockTime()); int error = mumps_data->info[0]; if (error < 0) { Jnlst().Printf(J_ERROR, J_LINEAR_ALGEBRA, "Error=%d returned from MUMPS in Solve.\n", error); retval = SYMSOLVER_FATAL_ERROR; } } if (HaveIpData()) { IpData().TimingStats().LinearSystemBackSolve().End(); } return retval; }
ESymSolverStatus Ma57TSolverInterface::Backsolve( Index nrhs, double *rhs_vals) { DBG_START_METH("Ma27TSolverInterface::Backsolve",dbg_verbosity); if (HaveIpData()) { IpData().TimingStats().LinearSystemBackSolve().Start(); } ipfint n = dim_; ipfint job = 1; ipfint nrhs_X = nrhs; ipfint lrhs = n; ipfint lwork; double* work; lwork = n * nrhs; work = new double[lwork]; // For each right hand side, call MA57CD // XXX MH: MA57 can do several RHSs; just do one solve... // AW: Ok is the following correct? if (DBG_VERBOSITY()>=2) { for (Index irhs=0; irhs<nrhs; irhs++) { for (Index i=0; i<dim_; i++) { DBG_PRINT((2, "rhs[%2d,%5d] = %23.15e\n", irhs, i, rhs_vals[irhs*dim_+i])); } } } F77_FUNC (ma57cd, MA57CD) (&job, &n, wd_fact_, &wd_lfact_, wd_ifact_, &wd_lifact_, &nrhs_X, rhs_vals, &lrhs, work, &lwork, wd_iwork_, wd_icntl_, wd_info_); if (wd_info_[0] != 0) Jnlst().Printf(J_ERROR, J_LINEAR_ALGEBRA, "Error in MA57CD: %d.\n", wd_info_[0]); if (DBG_VERBOSITY()>=2) { for (Index irhs=0; irhs<nrhs; irhs++) { for (Index i=0; i<dim_; i++) { DBG_PRINT((2, "sol[%2d,%5d] = %23.15e\n", irhs, i, rhs_vals[irhs*dim_+i])); } } } delete [] work; if (HaveIpData()) { IpData().TimingStats().LinearSystemBackSolve().End(); } return SYMSOLVER_SUCCESS; }
ESymSolverStatus IterativeWsmpSolverInterface::InternalSymFact( const Index* ia, const Index* ja) { if (HaveIpData()) { IpData().TimingStats().LinearSystemSymbolicFactorization().Start(); } // Call WISMP for ordering and symbolic factorization ipfint N = dim_; IPARM_[1] = 1; // ordering IPARM_[2] = 1; // symbolic factorization ipfint idmy; double ddmy; Jnlst().Printf(J_MOREDETAILED, J_LINEAR_ALGEBRA, "Calling WISMP-1-1 for symbolic analysis at cpu time %10.3f (wall %10.3f).\n", CpuTime(), WallclockTime()); F77_FUNC(wismp,WISMP)(&N, ia, ja, a_, &ddmy, &idmy, &ddmy, &idmy, &idmy, &ddmy, &ddmy, IPARM_, DPARM_); Jnlst().Printf(J_MOREDETAILED, J_LINEAR_ALGEBRA, "Done with WISMP-1-1 for symbolic analysis at cpu time %10.3f (wall %10.3f).\n", CpuTime(), WallclockTime()); Index ierror = IPARM_[63]; if (ierror!=0) { if (ierror==-102) { Jnlst().Printf(J_ERROR, J_LINEAR_ALGEBRA, "Error: WISMP is not able to allocate sufficient amount of memory during ordering/symbolic factorization.\n"); } else if (ierror>0) { Jnlst().Printf(J_DETAILED, J_LINEAR_ALGEBRA, "Matrix appears to be singular (with ierror = %d).\n", ierror); if (HaveIpData()) { IpData().TimingStats().LinearSystemSymbolicFactorization().End(); } return SYMSOLVER_SINGULAR; } else { Jnlst().Printf(J_ERROR, J_LINEAR_ALGEBRA, "Error in WISMP during ordering/symbolic factorization phase.\n Error code is %d.\n", ierror); } if (HaveIpData()) { IpData().TimingStats().LinearSystemSymbolicFactorization().End(); } return SYMSOLVER_FATAL_ERROR; } Jnlst().Printf(J_DETAILED, J_LINEAR_ALGEBRA, "Predicted memory usage for WISMP after symbolic factorization IPARM(23)= %d.\n", IPARM_[22]); if (HaveIpData()) { IpData().TimingStats().LinearSystemSymbolicFactorization().End(); } return SYMSOLVER_SUCCESS; }
/* Solve operation for multiple right hand sides. Solves the * linear system A * x = b with multiple right hand sides, where * A is the symmtric indefinite matrix. Here, ia and ja give the * positions of the values (in the required matrix data format). * The actual values of the matrix will have been given to this * object by copying them into the array provided by * GetValuesArrayPtr. ia and ja are identical to the ones given * to InitializeStructure. The flag new_matrix is set to true, * if the values of the matrix has changed, and a refactorzation * is required. * * The return code is SYMSOLV_SUCCESS if the factorization and * solves were successful, SYMSOLV_SINGULAR if the linear system * is singular, and SYMSOLV_WRONG_INERTIA if check_NegEVals is * true and the number of negative eigenvalues in the matrix does * not match numberOfNegEVals. If SYMSOLV_CALL_AGAIN is * returned, then the calling function will request the pointer * for the array for storing a again (with GetValuesPtr), write * the values of the nonzero elements into it, and call this * MultiSolve method again with the same right-hand sides. (This * can be done, for example, if the linear solver realized it * does not have sufficient memory and needs to redo the * factorization; e.g., for MA27.) * * The number of right-hand sides is given by nrhs, the values of * the right-hand sides are given in rhs_vals (one full right-hand * side stored immediately after the other), and solutions are * to be returned in the same array. * * check_NegEVals will not be chosen true, if ProvidesInertia() * returns false. */ ESymSolverStatus Ma86SolverInterface::MultiSolve(bool new_matrix, const Index* ia, const Index* ja, Index nrhs, double* rhs_vals, bool check_NegEVals, Index numberOfNegEVals) { struct ma86_info info; if (new_matrix || pivtol_changed_) { if (HaveIpData()) { IpData().TimingStats().LinearSystemFactorization().Start(); } //ma86_factor(ndim_, ia, ja, val_, order_, &keep_, &control_, &info); ma86_factor_solve(ndim_, ia, ja, val_, order_, &keep_, &control_, &info, nrhs, ndim_, rhs_vals, NULL); if (HaveIpData()) { IpData().TimingStats().LinearSystemFactorization().End(); } if (info.flag<0) return SYMSOLVER_FATAL_ERROR; if (info.flag==2 || info.flag==-3) return SYMSOLVER_SINGULAR; if (check_NegEVals && info.num_neg!=numberOfNegEVals) return SYMSOLVER_WRONG_INERTIA; /*if (HaveIpData()) { IpData().TimingStats().LinearSystemBackSolve().Start(); } ma86_solve(0, 1, ndim_, rhs_vals, order_, &keep_, &control_, &info); if (HaveIpData()) { IpData().TimingStats().LinearSystemBackSolve().End(); }*/ numneg_ = info.num_neg; pivtol_changed_ = false; } else { if (HaveIpData()) { IpData().TimingStats().LinearSystemBackSolve().Start(); } ma86_solve(0, nrhs, ndim_, rhs_vals, order_, &keep_, &control_, &info, NULL); if (HaveIpData()) { IpData().TimingStats().LinearSystemBackSolve().End(); } } return SYMSOLVER_SUCCESS; }
/* Solve operation for multiple right hand sides. Solves the * linear system A * x = b with multiple right hand sides, where * A is the symmtric indefinite matrix. Here, ia and ja give the * positions of the values (in the required matrix data format). * The actual values of the matrix will have been given to this * object by copying them into the array provided by * GetValuesArrayPtr. ia and ja are identical to the ones given * to InitializeStructure. The flag new_matrix is set to true, * if the values of the matrix has changed, and a refactorzation * is required. * * The return code is SYMSOLV_SUCCESS if the factorization and * solves were successful, SYMSOLV_SINGULAR if the linear system * is singular, and SYMSOLV_WRONG_INERTIA if check_NegEVals is * true and the number of negative eigenvalues in the matrix does * not match numberOfNegEVals. If SYMSOLV_CALL_AGAIN is * returned, then the calling function will request the pointer * for the array for storing a again (with GetValuesPtr), write * the values of the nonzero elements into it, and call this * MultiSolve method again with the same right-hand sides. (This * can be done, for example, if the linear solver realized it * does not have sufficient memory and needs to redo the * factorization; e.g., for MA27.) * * The number of right-hand sides is given by nrhs, the values of * the right-hand sides are given in rhs_vals (one full right-hand * side stored immediately after the other), and solutions are * to be returned in the same array. * * check_NegEVals will not be chosen true, if ProvidesInertia() * returns false. */ ESymSolverStatus Ma77SolverInterface::MultiSolve(bool new_matrix, const Index* ia, const Index* ja, Index nrhs, double* rhs_vals, bool check_NegEVals, Index numberOfNegEVals) { struct ma77_info info; if (new_matrix || pivtol_changed_) { for(int i=0; i<ndim_; i++) { ma77_input_reals(i+1, ia[i+1]-ia[i], &(val_[ia[i]-1]), &keep_, &control_, &info); if (info.flag < 0) return SYMSOLVER_FATAL_ERROR; } if (HaveIpData()) { IpData().TimingStats().LinearSystemFactorization().Start(); } //ma77_factor(0, &keep_, &control_, &info, NULL); ma77_factor_solve(0, &keep_, &control_, &info, NULL, nrhs, ndim_, rhs_vals); if (HaveIpData()) { IpData().TimingStats().LinearSystemFactorization().End(); } if (info.flag==4 || info.flag==-11) return SYMSOLVER_SINGULAR; if (info.flag<0) return SYMSOLVER_FATAL_ERROR; if (check_NegEVals && info.num_neg!=numberOfNegEVals) return SYMSOLVER_WRONG_INERTIA; numneg_ = info.num_neg; pivtol_changed_ = false; } else { if (HaveIpData()) { IpData().TimingStats().LinearSystemBackSolve().Start(); } ma77_solve(0, nrhs, ndim_, rhs_vals, &keep_, &control_, &info, NULL); if (HaveIpData()) { IpData().TimingStats().LinearSystemBackSolve().End(); } } return SYMSOLVER_SUCCESS; }
ESymSolverStatus Ma27TSolverInterface::Backsolve(Index nrhs, double *rhs_vals) { DBG_START_METH("Ma27TSolverInterface::Backsolve",dbg_verbosity); if (HaveIpData()) { IpData().TimingStats().LinearSystemBackSolve().Start(); } ipfint N=dim_; double* W = new double[maxfrt_]; ipfint* IW1 = new ipfint[nsteps_]; // For each right hand side, call MA27CD for (Index irhs=0; irhs<nrhs; irhs++) { if (DBG_VERBOSITY()>=2) { for (Index i=0; i<dim_; i++) { DBG_PRINT((2, "rhs[%5d] = %23.15e\n", i, rhs_vals[irhs*dim_+i])); } } F77_FUNC(ma27cd,MA27CD)(&N, a_, &la_, iw_, &liw_, W, &maxfrt_, &rhs_vals[irhs*dim_], IW1, &nsteps_, icntl_, cntl_); if (DBG_VERBOSITY()>=2) { for (Index i=0; i<dim_; i++) { DBG_PRINT((2, "sol[%5d] = %23.15e\n", i, rhs_vals[irhs*dim_+i])); } } } delete [] W; delete [] IW1; if (HaveIpData()) { IpData().TimingStats().LinearSystemBackSolve().End(); } return SYMSOLVER_SUCCESS; }
ESymSolverStatus Ma27TSolverInterface::Factorization(const Index* airn, const Index* ajcn, bool check_NegEVals, Index numberOfNegEVals) { DBG_START_METH("Ma27TSolverInterface::Factorization",dbg_verbosity); // Check if la should be increased if (HaveIpData()) { IpData().TimingStats().LinearSystemFactorization().Start(); } if (la_increase_) { double* a_old = a_; ipfint la_old = la_; la_ = (ipfint)(meminc_factor_ * (double)(la_)); a_ = new double[la_]; for (Index i=0; i<nonzeros_; i++) { a_[i] = a_old[i]; } delete [] a_old; la_increase_ = false; Jnlst().Printf(J_DETAILED, J_LINEAR_ALGEBRA, "In Ma27TSolverInterface::Factorization: Increasing la from %d to %d\n", la_old, la_); } // Check if liw should be increased if (liw_increase_) { delete [] iw_; iw_ = NULL; ipfint liw_old = liw_; liw_ = (ipfint)(meminc_factor_ * (double)(liw_)); iw_ = new ipfint[liw_]; liw_increase_ = false; Jnlst().Printf(J_DETAILED, J_LINEAR_ALGEBRA, "In Ma27TSolverInterface::Factorization: Increasing liw from %d to %d\n", liw_old, liw_); } ipfint iflag; // Information flag ipfint ncmpbr; // Number of double precision compressions ipfint ncmpbi; // Number of integer compressions // Call MA27BD; possibly repeatedly if workspaces are too small ipfint N=dim_; ipfint NZ=nonzeros_; ipfint* IW1 = new ipfint[2*dim_]; ipfint INFO[20]; cntl_[0] = pivtol_; // Set pivot tolerance F77_FUNC(ma27bd,MA27BD)(&N, &NZ, airn, ajcn, a_, &la_, iw_, &liw_, ikeep_, &nsteps_, &maxfrt_, IW1, icntl_, cntl_, INFO); delete [] IW1; // Receive information about the factorization iflag = INFO[0]; // Information flag const ipfint &ierror = INFO[1]; // Error flag ncmpbr = INFO[11]; // Number of double compressions ncmpbi = INFO[12]; // Number of integer compressions negevals_ = INFO[14]; // Number of negative eigenvalues Jnlst().Printf(J_MOREDETAILED, J_LINEAR_ALGEBRA, "Return values from MA27BD: IFLAG = %d, IERROR = %d\n", iflag, ierror); DBG_PRINT((1,"Return from MA27BD iflag = %d and ierror = %d\n", iflag, ierror)); // Check if factorization failed due to insufficient memory space // iflag==-3 if LIW too small (recommended value in ierror) // iflag==-4 if LA too small (recommended value in ierror) if (iflag==-3 || iflag==-4) { // Increase size of both LIW and LA delete [] iw_; iw_ = NULL; delete [] a_; a_ = NULL; ipfint liw_old = liw_; ipfint la_old = la_; if (iflag==-3) { liw_ = (ipfint)(meminc_factor_ * (double)(ierror)); la_ = (ipfint)(meminc_factor_ * (double)(la_)); } else { liw_ = (ipfint)(meminc_factor_ * (double)(liw_)); la_ = (ipfint)(meminc_factor_ * (double)(ierror)); } iw_ = new ipfint[liw_]; a_ = new double[la_]; Jnlst().Printf(J_WARNING, J_LINEAR_ALGEBRA, "MA27BD returned iflag=%d and requires more memory.\n Increase liw from %d to %d and la from %d to %d and factorize again.\n", iflag, liw_old, liw_, la_old, la_); if (HaveIpData()) { IpData().TimingStats().LinearSystemFactorization().End(); } return SYMSOLVER_CALL_AGAIN; } // Check if the system is singular, and if some other error occurred if (iflag==-5 || (!ignore_singularity_ && iflag==3)) { if (HaveIpData()) { IpData().TimingStats().LinearSystemFactorization().End(); } return SYMSOLVER_SINGULAR; } else if (iflag==3) { Index missing_rank = dim_-INFO[1]; Jnlst().Printf(J_WARNING, J_LINEAR_ALGEBRA, "MA27BD returned iflag=%d and detected rank deficiency of degree %d.\n", iflag, missing_rank); // We correct the number of negative eigenvalues here to include // the zero eigenvalues, since otherwise we indicate the wrong // inertia. negevals_ += missing_rank; } else if (iflag != 0) { // There is some error if (HaveIpData()) { IpData().TimingStats().LinearSystemFactorization().End(); } return SYMSOLVER_FATAL_ERROR; } // Check if it might be more efficient to use more memory next time // (if there were too many compressions for this factorization) if (ncmpbr>=10) { la_increase_ = true; Jnlst().Printf(J_WARNING, J_LINEAR_ALGEBRA, "MA27BD returned ncmpbr=%d. Increase la before the next factorization.\n", ncmpbr); } if (ncmpbi>=10) { liw_increase_ = true; Jnlst().Printf(J_WARNING, J_LINEAR_ALGEBRA, "MA27BD returned ncmpbi=%d. Increase liw before the next factorization.\n", ncmpbr); } Jnlst().Printf(J_DETAILED, J_LINEAR_ALGEBRA, "Number of doubles for MA27 to hold factorization (INFO(9)) = %d\n", INFO[8]); Jnlst().Printf(J_DETAILED, J_LINEAR_ALGEBRA, "Number of integers for MA27 to hold factorization (INFO(10)) = %d\n", INFO[9]); // Check whether the number of negative eigenvalues matches the requested // count if (HaveIpData()) { IpData().TimingStats().LinearSystemFactorization().End(); } if (!skip_inertia_check_ && check_NegEVals && (numberOfNegEVals!=negevals_)) { Jnlst().Printf(J_DETAILED, J_LINEAR_ALGEBRA, "In Ma27TSolverInterface::Factorization: negevals_ = %d, but numberOfNegEVals = %d\n", negevals_, numberOfNegEVals); return SYMSOLVER_WRONG_INERTIA; } return SYMSOLVER_SUCCESS; }
ESymSolverStatus IterativeWsmpSolverInterface::Solve( const Index* ia, const Index* ja, Index nrhs, double *rhs_vals) { DBG_START_METH("IterativeWsmpSolverInterface::Solve",dbg_verbosity); if (HaveIpData()) { IpData().TimingStats().LinearSystemBackSolve().Start(); } // Call WISMP to solve for some right hand sides. The solution // will be stored in rhs_vals, and we need to make a copy of the // original right hand side before the call. ipfint N = dim_; ipfint LDB = dim_; double* RHS = new double[dim_*nrhs]; IpBlasDcopy(dim_*nrhs, rhs_vals, 1, RHS, 1); ipfint LDX = dim_; // Q: Do we have to zero out solution? ipfint NRHS = nrhs; IPARM_[1] = 4; // Iterative solver solution IPARM_[2] = 4; double* CVGH = NULL; if (Jnlst().ProduceOutput(J_MOREDETAILED, J_LINEAR_ALGEBRA)) { IPARM_[26] = 1; // Record convergence history CVGH = new double[IPARM_[5]+1]; } else { IPARM_[26] = 0; } double ddmy; Jnlst().Printf(J_MOREDETAILED, J_LINEAR_ALGEBRA, "Calling WISMP-4-4 for backsolve at cpu time %10.3f (wall %10.3f).\n", CpuTime(), WallclockTime()); F77_FUNC(wismp,WISMP)(&N, ia, ja, a_, RHS, &LDB, rhs_vals, &LDX, &NRHS, &ddmy, CVGH, IPARM_, DPARM_); Jnlst().Printf(J_MOREDETAILED, J_LINEAR_ALGEBRA, "Done with WISMP-4-4 for backsolve at cpu time %10.3f (wall %10.3f).\n", CpuTime(), WallclockTime()); if (HaveIpData()) { IpData().TimingStats().LinearSystemBackSolve().End(); } Index ierror = IPARM_[63]; if (ierror!=0) { if (ierror==-102) { Jnlst().Printf(J_ERROR, J_LINEAR_ALGEBRA, "Error: WISMP is not able to allocate sufficient amount of memory during ordering/symbolic factorization.\n"); } else { Jnlst().Printf(J_ERROR, J_LINEAR_ALGEBRA, "Error in WISMP during ordering/symbolic factorization phase.\n Error code is %d.\n", ierror); } return SYMSOLVER_FATAL_ERROR; } Jnlst().Printf(J_DETAILED, J_LINEAR_ALGEBRA, "Number of itertive solver steps in WISMP: %d\n", IPARM_[25]); if (Jnlst().ProduceOutput(J_MOREDETAILED, J_LINEAR_ALGEBRA)) { Jnlst().Printf(J_MOREDETAILED, J_LINEAR_ALGEBRA, "WISMP congergence history:\n"); for (Index i=0; i<=IPARM_[25]; ++i) { Jnlst().Printf(J_MOREDETAILED, J_LINEAR_ALGEBRA, " Resid[%3d] = %13.6e\n", i, CVGH[i]); } delete [] CVGH; } return SYMSOLVER_SUCCESS; }
ESymSolverStatus Ma27TSolverInterface::SymbolicFactorization(const Index* airn, const Index* ajcn) { DBG_START_METH("Ma27TSolverInterface::SymbolicFactorization",dbg_verbosity); if (HaveIpData()) { IpData().TimingStats().LinearSystemSymbolicFactorization().Start(); } // Get memory for the IW workspace delete [] iw_; iw_ = NULL; // Overestimation factor for LIW (20% recommended in MA27 documentation) const double LiwFact = 2.0; // This is 100% overestimation Jnlst().Printf(J_DETAILED, J_LINEAR_ALGEBRA, "In Ma27TSolverInterface::InitializeStructure: Using overestimation factor LiwFact = %e\n", LiwFact); liw_ = (ipfint)(LiwFact*(double(2*nonzeros_+3*dim_+1))); iw_ = new ipfint[liw_]; // Get memory for IKEEP delete [] ikeep_; ikeep_ = NULL; ikeep_ = new ipfint[3*dim_]; if (Jnlst().ProduceOutput(J_MOREMATRIX, J_LINEAR_ALGEBRA)) { Jnlst().Printf(J_MOREMATRIX, J_LINEAR_ALGEBRA, "\nMatrix structure given to MA27 with dimension %d and %d nonzero entries:\n", dim_, nonzeros_); for (Index i=0; i<nonzeros_; i++) { Jnlst().Printf(J_MOREMATRIX, J_LINEAR_ALGEBRA, "A[%5d,%5d]\n", airn[i], ajcn[i]); } } // Call MA27AD (cast to ipfint for Index types) ipfint N = dim_; ipfint NZ = nonzeros_; ipfint IFLAG = 0; double OPS; ipfint INFO[20]; ipfint* IW1 = new ipfint[2*dim_]; // Get memory for IW1 (only local) F77_FUNC(ma27ad,MA27AD)(&N, &NZ, airn, ajcn, iw_, &liw_, ikeep_, IW1, &nsteps_, &IFLAG, icntl_, cntl_, INFO, &OPS); delete [] IW1; // No longer required // Receive several information const ipfint &iflag = INFO[0]; // Information flag const ipfint &ierror = INFO[1]; // Error flag const ipfint &nrlnec = INFO[4]; // recommended value for la const ipfint &nirnec = INFO[5]; // recommended value for liw Jnlst().Printf(J_MOREDETAILED, J_LINEAR_ALGEBRA, "Return values from MA27AD: IFLAG = %d, IERROR = %d\n", iflag, ierror); // Check if error occurred if (iflag!=0) { Jnlst().Printf(J_ERROR, J_LINEAR_ALGEBRA, "*** Error from MA27AD *** IFLAG = %d IERROR = %d\n", iflag, ierror); if (iflag==1) { Jnlst().Printf(J_ERROR, J_LINEAR_ALGEBRA, "The index of a matrix is out of range.\nPlease check your implementation of the Jacobian and Hessian matrices.\n"); } if (HaveIpData()) { IpData().TimingStats().LinearSystemSymbolicFactorization().End(); } return SYMSOLVER_FATAL_ERROR; } // ToDo: try and catch // Reserve memory for iw_ for later calls, based on suggested size delete [] iw_; iw_ = NULL; Jnlst().Printf(J_DETAILED, J_LINEAR_ALGEBRA, "Size of integer work space recommended by MA27 is %d\n", nirnec); liw_ = (ipfint)(liw_init_factor_ * (double)(nirnec)); Jnlst().Printf(J_DETAILED, J_LINEAR_ALGEBRA, "Setting integer work space size to %d\n", liw_); iw_ = new ipfint[liw_]; // Reserve memory for a_ delete [] a_; a_ = NULL; Jnlst().Printf(J_DETAILED, J_LINEAR_ALGEBRA, "Size of doublespace recommended by MA27 is %d\n", nrlnec); la_ = Max(nonzeros_,(ipfint)(la_init_factor_ * (double)(nrlnec))); Jnlst().Printf(J_DETAILED, J_LINEAR_ALGEBRA, "Setting double work space size to %d\n", la_); a_ = new double[la_]; if (HaveIpData()) { IpData().TimingStats().LinearSystemSymbolicFactorization().End(); } return SYMSOLVER_SUCCESS; }
ESymSolverStatus MumpsSolverInterface::SymbolicFactorization() { DBG_START_METH("MumpsSolverInterface::SymbolicFactorization", dbg_verbosity); DMUMPS_STRUC_C* mumps_data = (DMUMPS_STRUC_C*)mumps_ptr_; if (HaveIpData()) { IpData().TimingStats().LinearSystemSymbolicFactorization().Start(); } mumps_data->job = 1;//symbolic ordering pass //mumps_data->icntl[1] = 6; //mumps_data->icntl[2] = 6;//QUIETLY! //mumps_data->icntl[3] = 4; mumps_data->icntl[5] = mumps_permuting_scaling_; mumps_data->icntl[6] = mumps_pivot_order_; mumps_data->icntl[7] = mumps_scaling_; mumps_data->icntl[9] = 0;//no iterative refinement iterations mumps_data->icntl[12] = 1;//avoid lapack bug, ensures proper inertia mumps_data->icntl[13] = mem_percent_; //% memory to allocate over expected mumps_data->cntl[0] = pivtol_; // Set pivot tolerance dump_matrix(mumps_data); Jnlst().Printf(J_MOREDETAILED, J_LINEAR_ALGEBRA, "Calling MUMPS-1 for symbolic factorization at cpu time %10.3f (wall %10.3f).\n", CpuTime(), WallclockTime()); dmumps_c(mumps_data); Jnlst().Printf(J_MOREDETAILED, J_LINEAR_ALGEBRA, "Done with MUMPS-1 for symbolic factorization at cpu time %10.3f (wall %10.3f).\n", CpuTime(), WallclockTime()); int error = mumps_data->info[0]; const int& mumps_permuting_scaling_used = mumps_data->infog[22]; const int& mumps_pivot_order_used = mumps_data->infog[6]; Jnlst().Printf(J_DETAILED, J_LINEAR_ALGEBRA, "MUMPS used permuting_scaling %d and pivot_order %d.\n", mumps_permuting_scaling_used, mumps_pivot_order_used); Jnlst().Printf(J_DETAILED, J_LINEAR_ALGEBRA, " scaling will be %d.\n", mumps_data->icntl[7]); if (HaveIpData()) { IpData().TimingStats().LinearSystemSymbolicFactorization().End(); } //return appropriat value if (error == -6) {//system is singular Jnlst().Printf(J_DETAILED, J_LINEAR_ALGEBRA, "MUMPS returned INFO(1) = %d matrix is singular.\n",error); return SYMSOLVER_SINGULAR; } if (error < 0) { Jnlst().Printf(J_ERROR, J_LINEAR_ALGEBRA, "Error=%d returned from MUMPS in Factorization.\n", error); return SYMSOLVER_FATAL_ERROR; } return SYMSOLVER_SUCCESS; }
ESymSolverStatus WsmpSolverInterface::Factorization( const Index* ia, const Index* ja, bool check_NegEVals, Index numberOfNegEVals) { DBG_START_METH("WsmpSolverInterface::Factorization",dbg_verbosity); // If desired, write out the matrix Index iter_count = -1; if (HaveIpData()) { iter_count = IpData().iter_count(); } if (iter_count == wsmp_write_matrix_iteration_) { matrix_file_number_++; char buf[256]; Snprintf(buf, 255, "wsmp_matrix_%d_%d.dat", iter_count, matrix_file_number_); Jnlst().Printf(J_SUMMARY, J_LINEAR_ALGEBRA, "Writing WSMP matrix into file %s.\n", buf); FILE* fp = fopen(buf, "w"); fprintf(fp, "%d\n", dim_); // N for (Index icol=0; icol<dim_; icol++) { fprintf(fp, "%d", ia[icol+1]-ia[icol]); // number of elements for this column // Now for each colum we write row indices and values for (Index irow=ia[icol]; irow<ia[icol+1]; irow++) { fprintf(fp, " %23.16e %d",a_[irow-1],ja[irow-1]); } fprintf(fp, "\n"); } fclose(fp); } // Check if we have to do the symbolic factorization and ordering // phase yet if (!have_symbolic_factorization_) { ESymSolverStatus retval = InternalSymFact(ia, ja, numberOfNegEVals); if (retval != SYMSOLVER_SUCCESS) { return retval; } have_symbolic_factorization_ = true; } if (HaveIpData()) { IpData().TimingStats().LinearSystemFactorization().Start(); } // Call WSSMP for numerical factorization ipfint N = dim_; ipfint NAUX = 0; IPARM_[1] = 3; // numerical factorization IPARM_[2] = 3; // numerical factorization DPARM_[10] = wsmp_pivtol_; // set current pivot tolerance ipfint idmy; double ddmy; #ifdef PARDISO_MATCHING_PREPROCESS { ipfint* tmp2_ = new ipfint[N]; smat_reordering_pardiso_wsmp_ (&N, ia, ja, a_, ia2, ja2, a2_, perm2, scale2, tmp2_, 1); delete[] tmp2_; } #endif Jnlst().Printf(J_MOREDETAILED, J_LINEAR_ALGEBRA, "Calling WSSMP-3-3 for numerical factorization at cpu time %10.3f (wall %10.3f).\n", CpuTime(), WallclockTime()); #ifdef PARDISO_MATCHING_PREPROCESS F77_FUNC(wssmp,WSSMP)(&N, ia2, ja2, a2_, &ddmy, PERM_, INVP_, &ddmy, &idmy, #else F77_FUNC(wssmp,WSSMP)(&N, ia, ja, a_, &ddmy, PERM_, INVP_, &ddmy, &idmy, #endif &idmy, &ddmy, &NAUX, MRP_, IPARM_, DPARM_); Jnlst().Printf(J_MOREDETAILED, J_LINEAR_ALGEBRA, "Done with WSSMP-3-3 for numerical factorization at cpu time %10.3f (wall %10.3f).\n", CpuTime(), WallclockTime()); const Index ierror = IPARM_[63]; if (ierror > 0) { Jnlst().Printf(J_DETAILED, J_LINEAR_ALGEBRA, "WSMP detected that the matrix is singular and encountered %d zero pivots.\n", dim_+1-ierror); if (HaveIpData()) { IpData().TimingStats().LinearSystemFactorization().End(); } return SYMSOLVER_SINGULAR; } else if (ierror != 0) { if (ierror == -102) { Jnlst().Printf(J_ERROR, J_LINEAR_ALGEBRA, "Error: WSMP is not able to allocate sufficient amount of memory during factorization.\n"); } else { Jnlst().Printf(J_ERROR, J_LINEAR_ALGEBRA, "Error in WSMP during factorization phase.\n Error code is %d.\n", ierror); } if (HaveIpData()) { IpData().TimingStats().LinearSystemFactorization().End(); } return SYMSOLVER_FATAL_ERROR; } Jnlst().Printf(J_DETAILED, J_LINEAR_ALGEBRA, "Memory usage for WSSMP after factorization IPARM(23) = %d\n", IPARM_[22]); Jnlst().Printf(J_DETAILED, J_LINEAR_ALGEBRA, "Number of nonzeros in WSSMP after factorization IPARM(24) = %d\n", IPARM_[23]); if (factorizations_since_recomputed_ordering_ != -1) { factorizations_since_recomputed_ordering_++; } negevals_ = IPARM_[21]; // Number of negative eigenvalues determined during factorization // Check whether the number of negative eigenvalues matches the requested // count if (check_NegEVals && (numberOfNegEVals!=negevals_)) { Jnlst().Printf(J_DETAILED, J_LINEAR_ALGEBRA, "Wrong inertia: required are %d, but we got %d.\n", numberOfNegEVals, negevals_); if (skip_inertia_check_) { Jnlst().Printf(J_DETAILED, J_LINEAR_ALGEBRA, " But wsmp_skip_inertia_check is set. Ignore inertia.\n"); IpData().Append_info_string("IC "); negevals_ = numberOfNegEVals; } else { if (HaveIpData()) { IpData().TimingStats().LinearSystemFactorization().End(); } return SYMSOLVER_WRONG_INERTIA; } } if (HaveIpData()) { IpData().TimingStats().LinearSystemFactorization().End(); } return SYMSOLVER_SUCCESS; }
/* Method for initializing internal structures. Here, ndim gives * the number of rows and columns of the matrix, nonzeros give * the number of nonzero elements, and ia and ja give the * positions of the nonzero elements, given in the matrix format * determined by MatrixFormat. */ ESymSolverStatus Ma77SolverInterface::InitializeStructure(Index dim, Index nonzeros, const Index* ia, const Index* ja) { struct ma77_info info; struct mc68_control control68; struct mc68_info info68; // Store size for later use ndim_ = dim; if (HaveIpData()) { IpData().TimingStats().LinearSystemSymbolicFactorization().Start(); } // mc68 requires a half matrix. A future version will support full // matrix entry, and this code should be removed when it is available. Index *ia_half = new Index[dim+1]; Index *ja_half = new Index[ia[dim]-1]; { int k = 0; for(int i=0; i<dim; i++) { ia_half[i] = k+1; for(int j=ia[i]-1; j<ia[i+1]-1; j++) if(ja[j]-1 >= i) ja_half[k++] = ja[j]; } ia_half[dim] = k+1; } // Determine an ordering mc68_default_control(&control68); control68.f_array_in = 1; // Use Fortran numbering (faster) control68.f_array_out = 1; // Use Fortran numbering (faster) Index *perm = new Index[dim]; if(ordering_ == ORDER_METIS) { mc68_order(3, dim, ia_half, ja_half, perm, &control68, &info68); /* MeTiS */ if(info68.flag == -5) { // MeTiS not available ordering_ = ORDER_AMD; } else if(info68.flag<0) { delete[] ia_half; delete[] ja_half; return SYMSOLVER_FATAL_ERROR; } } if(ordering_ == ORDER_AMD) { mc68_order(1, dim, ia_half, ja_half, perm, &control68, &info68); /* AMD */ if(info68.flag<0) { delete[] ia_half; delete[] ja_half; return SYMSOLVER_FATAL_ERROR; } } delete[] ia_half; delete[] ja_half; // Open files ma77_open(ndim_, "ma77_int", "ma77_real", "ma77_work", "ma77_delay", &keep_, &control_, &info); if (info.flag < 0) return SYMSOLVER_FATAL_ERROR; // Store data into files for(int i=0; i<dim; i++) { ma77_input_vars(i+1, ia[i+1]-ia[i], &(ja[ia[i]-1]), &keep_, &control_, &info); if (info.flag < 0) return SYMSOLVER_FATAL_ERROR; } // Perform analyse ma77_analyse(perm, &keep_, &control_, &info); delete[] perm; // Done with order if (HaveIpData()) IpData().TimingStats().LinearSystemSymbolicFactorization().End(); // Setup memory for values if (val_!=NULL) delete[] val_; val_ = new double[nonzeros]; if (info.flag>=0) { return SYMSOLVER_SUCCESS; } else { return SYMSOLVER_FATAL_ERROR; } }
ESymSolverStatus IterativePardisoSolverInterface::Factorization(const Index* ia, const Index* ja, bool check_NegEVals, Index numberOfNegEVals) { DBG_START_METH("IterativePardisoSolverInterface::Factorization",dbg_verbosity); // Call Pardiso to do the factorization ipfint PHASE ; ipfint N = dim_; ipfint PERM; // This should not be accessed by Pardiso ipfint NRHS = 0; double B; // This should not be accessed by Pardiso in factorization // phase double X; // This should not be accessed by Pardiso in factorization // phase ipfint ERROR; bool done = false; bool just_performed_symbolic_factorization = false; while (!done) { bool is_normal = false; if (IsNull(InexData().normal_x()) && InexData().compute_normal()) { is_normal = true; } if (!have_symbolic_factorization_) { if (HaveIpData()) { IpData().TimingStats().LinearSystemSymbolicFactorization().Start(); } PHASE = 11; Jnlst().Printf(J_DETAILED, J_LINEAR_ALGEBRA, "Calling Pardiso for symbolic factorization.\n"); if (is_normal) { DPARM_[ 0] = normal_pardiso_max_iter_; DPARM_[ 1] = normal_pardiso_iter_relative_tol_; DPARM_[ 2] = normal_pardiso_iter_coarse_size_; DPARM_[ 3] = normal_pardiso_iter_max_levels_; DPARM_[ 4] = normal_pardiso_iter_dropping_factor_used_; DPARM_[ 5] = normal_pardiso_iter_dropping_schur_used_; DPARM_[ 6] = normal_pardiso_iter_max_row_fill_; DPARM_[ 7] = normal_pardiso_iter_inverse_norm_factor_; } else { DPARM_[ 0] = pardiso_max_iter_; DPARM_[ 1] = pardiso_iter_relative_tol_; DPARM_[ 2] = pardiso_iter_coarse_size_; DPARM_[ 3] = pardiso_iter_max_levels_; DPARM_[ 4] = pardiso_iter_dropping_factor_used_; DPARM_[ 5] = pardiso_iter_dropping_schur_used_; DPARM_[ 6] = pardiso_iter_max_row_fill_; DPARM_[ 7] = pardiso_iter_inverse_norm_factor_; } DPARM_[ 8] = 25; // maximum number of non-improvement steps F77_FUNC(pardiso,PARDISO)(PT_, &MAXFCT_, &MNUM_, &MTYPE_, &PHASE, &N, a_, ia, ja, &PERM, &NRHS, IPARM_, &MSGLVL_, &B, &X, &ERROR, DPARM_); if (HaveIpData()) { IpData().TimingStats().LinearSystemSymbolicFactorization().End(); } if (ERROR==-7) { Jnlst().Printf(J_MOREDETAILED, J_LINEAR_ALGEBRA, "Pardiso symbolic factorization returns ERROR = %d. Matrix is singular.\n", ERROR); return SYMSOLVER_SINGULAR; } else if (ERROR!=0) { Jnlst().Printf(J_ERROR, J_LINEAR_ALGEBRA, "Error in Pardiso during symbolic factorization phase. ERROR = %d.\n", ERROR); return SYMSOLVER_FATAL_ERROR; } have_symbolic_factorization_ = true; just_performed_symbolic_factorization = true; Jnlst().Printf(J_DETAILED, J_LINEAR_ALGEBRA, "Memory in KB required for the symbolic factorization = %d.\n", IPARM_[14]); Jnlst().Printf(J_DETAILED, J_LINEAR_ALGEBRA, "Integer memory in KB required for the numerical factorization = %d.\n", IPARM_[15]); Jnlst().Printf(J_DETAILED, J_LINEAR_ALGEBRA, "Double memory in KB required for the numerical factorization = %d.\n", IPARM_[16]); } PHASE = 22; if (HaveIpData()) { IpData().TimingStats().LinearSystemFactorization().Start(); } Jnlst().Printf(J_MOREDETAILED, J_LINEAR_ALGEBRA, "Calling Pardiso for factorization.\n"); // Dump matrix to file, and count number of solution steps. if (HaveIpData()) { if (IpData().iter_count() != debug_last_iter_) debug_cnt_ = 0; debug_last_iter_ = IpData().iter_count(); debug_cnt_ ++; } else { debug_cnt_ = 0; debug_last_iter_ = 0; } if (is_normal) { DPARM_[ 0] = normal_pardiso_max_iter_; DPARM_[ 1] = normal_pardiso_iter_relative_tol_; DPARM_[ 2] = normal_pardiso_iter_coarse_size_; DPARM_[ 3] = normal_pardiso_iter_max_levels_; DPARM_[ 4] = normal_pardiso_iter_dropping_factor_used_; DPARM_[ 5] = normal_pardiso_iter_dropping_schur_used_; DPARM_[ 6] = normal_pardiso_iter_max_row_fill_; DPARM_[ 7] = normal_pardiso_iter_inverse_norm_factor_; } else { DPARM_[ 0] = pardiso_max_iter_; DPARM_[ 1] = pardiso_iter_relative_tol_; DPARM_[ 2] = pardiso_iter_coarse_size_; DPARM_[ 3] = pardiso_iter_max_levels_; DPARM_[ 4] = pardiso_iter_dropping_factor_used_; DPARM_[ 5] = pardiso_iter_dropping_schur_used_; DPARM_[ 6] = pardiso_iter_max_row_fill_; DPARM_[ 7] = pardiso_iter_inverse_norm_factor_; } DPARM_[ 8] = 25; // maximum number of non-improvement steps F77_FUNC(pardiso,PARDISO)(PT_, &MAXFCT_, &MNUM_, &MTYPE_, &PHASE, &N, a_, ia, ja, &PERM, &NRHS, IPARM_, &MSGLVL_, &B, &X, &ERROR, DPARM_); if (HaveIpData()) { IpData().TimingStats().LinearSystemFactorization().End(); } if (ERROR==-7) { Jnlst().Printf(J_MOREDETAILED, J_LINEAR_ALGEBRA, "Pardiso factorization returns ERROR = %d. Matrix is singular.\n", ERROR); return SYMSOLVER_SINGULAR; } else if (ERROR==-4) { // I think this means that the matrix is singular // OLAF said that this will never happen (ToDo) return SYMSOLVER_SINGULAR; } else if (ERROR!=0 ) { Jnlst().Printf(J_ERROR, J_LINEAR_ALGEBRA, "Error in Pardiso during factorization phase. ERROR = %d.\n", ERROR); return SYMSOLVER_FATAL_ERROR; } negevals_ = Max(IPARM_[22], numberOfNegEVals); if (IPARM_[13] != 0) { Jnlst().Printf(J_DETAILED, J_LINEAR_ALGEBRA, "Number of perturbed pivots in factorization phase = %d.\n", IPARM_[13]); if (HaveIpData()) { IpData().Append_info_string("Pp"); } done = true; } else { done = true; } } // DBG_ASSERT(IPARM_[21]+IPARM_[22] == dim_); // Check whether the number of negative eigenvalues matches the requested // count if (skip_inertia_check_) numberOfNegEVals=negevals_; if (check_NegEVals && (numberOfNegEVals!=negevals_)) { Jnlst().Printf(J_DETAILED, J_LINEAR_ALGEBRA, "Wrong inertia: required are %d, but we got %d.\n", numberOfNegEVals, negevals_); return SYMSOLVER_WRONG_INERTIA; } return SYMSOLVER_SUCCESS; }
ESymSolverStatus Ma57TSolverInterface::Factorization(const Index* airn, const Index* ajcn, bool check_NegEVals, Index numberOfNegEVals) { DBG_START_METH("Ma57TSolverInterface::Factorization",dbg_verbosity); if (HaveIpData()) { IpData().TimingStats().LinearSystemFactorization().Start(); } int fact_error = 1; wd_cntl_[1-1] = pivtol_; /* Pivot threshold. */ ipfint n = dim_; ipfint ne = nonzeros_; while (fact_error > 0) { F77_FUNC (ma57bd, MA57BD) (&n, &ne, a_, wd_fact_, &wd_lfact_, wd_ifact_, &wd_lifact_, &wd_lkeep_, wd_keep_, wd_iwork_, wd_icntl_, wd_cntl_, wd_info_, wd_rinfo_); negevals_ = wd_info_[24-1]; // Number of negative eigenvalues if (wd_info_[0] == 0) { fact_error = 0; } else if (wd_info_[0] == -3) { /* Failure due to insufficient REAL space on a call to MA57B/BD. * INFO(17) is set to a value that may suffice. INFO(2) is set * to value of LFACT. The user can allocate a larger array and * copy the contents of FACT into it using MA57E/ED, and recall * MA57B/BD. */ double *temp; ipfint ic = 0; wd_lfact_ = (ipfint)((Number)wd_info_[16] * ma57_pre_alloc_); temp = new double[wd_lfact_]; Jnlst().Printf(J_WARNING, J_LINEAR_ALGEBRA, "Reallocating memory for MA57: lfact (%d)\n", wd_lfact_); ipfint idmy; F77_FUNC (ma57ed, MA57ED) (&n, &ic, wd_keep_, wd_fact_, &wd_info_[1], temp, &wd_lfact_, wd_ifact_, &wd_info_[1], &idmy, &wd_lfact_, wd_info_); delete [] wd_fact_; wd_fact_ = temp; } else if (wd_info_[0] == -4) { /* Failure due to insufficient INTEGER space on a call to * MA57B/BD. INFO(18) is set to a value that may suffice. * INFO(2) is set to value of LIFACT. The user can allocate a * larger array and copy the contents of IFACT into it using * MA57E/ED, and recall MA57B/BD. */ ipfint *temp; ipfint ic = 1; wd_lifact_ = (ipfint)((Number)wd_info_[17] * ma57_pre_alloc_); temp = new ipfint[wd_lifact_]; Jnlst().Printf(J_DETAILED, J_LINEAR_ALGEBRA, "Reallocating lifact (%d)\n", wd_lifact_); double ddmy; F77_FUNC (ma57ed, MA57ED) (&n, &ic, wd_keep_, wd_fact_, &wd_info_[1], &ddmy, &wd_lifact_, wd_ifact_, &wd_info_[1], temp, &wd_lifact_, wd_info_); delete [] wd_ifact_; wd_ifact_ = temp; } else if (wd_info_[0] < 0) { Jnlst().Printf(J_ERROR, J_LINEAR_ALGEBRA, "Error in MA57BD: %d\n", wd_info_[0]); Jnlst().Printf(J_DETAILED, J_LINEAR_ALGEBRA, "MA57 Error message: %s\n", ma57_err_msg[-wd_info_[1-1]]); return SYMSOLVER_FATAL_ERROR; } // Check if the system is singular. else if (wd_info_[0] == 4) { if (HaveIpData()) { IpData().TimingStats().LinearSystemFactorization().End(); } Jnlst().Printf(J_DETAILED, J_LINEAR_ALGEBRA, "System singular, rank = %d\n", wd_info_[25-1]); return SYMSOLVER_SINGULAR; } else if (wd_info_[0] > 0) { Jnlst().Printf(J_ERROR, J_LINEAR_ALGEBRA, "Warning in MA57BD: %d\n", wd_info_[0]); Jnlst().Printf(J_DETAILED, J_LINEAR_ALGEBRA, "MA57 Warning message: %s\n", ma57_wrn_msg[wd_info_[1-1]]); // For now, abort the process so that we don't miss any problems return SYMSOLVER_FATAL_ERROR; } } double peak_mem = 1.0e-3 * (wd_lfact_*8.0 + wd_lifact_*4.0 + wd_lkeep_*4.0); Jnlst().Printf(J_DETAILED, J_LINEAR_ALGEBRA, "MA57 peak memory use: %dKB\n", (ipfint)(peak_mem)); // Check whether the number of negative eigenvalues matches the // requested count. if (HaveIpData()) { IpData().TimingStats().LinearSystemFactorization().End(); } if (check_NegEVals && (numberOfNegEVals!=negevals_)) { Jnlst().Printf(J_DETAILED, J_LINEAR_ALGEBRA, "In Ma57TSolverInterface::Factorization: " "negevals_ = %d, but numberOfNegEVals = %d\n", negevals_, numberOfNegEVals); return SYMSOLVER_WRONG_INERTIA; } return SYMSOLVER_SUCCESS; }
ESymSolverStatus PardisoSolverInterface::Solve(const Index* ia, const Index* ja, Index nrhs, double *rhs_vals) { DBG_START_METH("PardisoSolverInterface::Solve",dbg_verbosity); if (HaveIpData()) { IpData().TimingStats().LinearSystemBackSolve().Start(); } // Call Pardiso to do the solve for the given right-hand sides ipfint PHASE = 33; ipfint N = dim_; ipfint PERM; // This should not be accessed by Pardiso ipfint NRHS = nrhs; double* X = new double[nrhs*dim_]; double* ORIG_RHS = new double[nrhs*dim_]; ipfint ERROR; // Initialize solution with zero and save right hand side for (int i = 0; i < N; i++) { X[i] = 0.; ORIG_RHS[i] = rhs_vals[i]; } // Dump matrix to file if requested Index iter_count = 0; if (HaveIpData()) { iter_count = IpData().iter_count(); } #ifdef PARDISO_MATCHING_PREPROCESS write_iajaa_matrix (N, ia2, ja2, a2_, rhs_vals, iter_count, debug_cnt_); #else write_iajaa_matrix (N, ia, ja, a_, rhs_vals, iter_count, debug_cnt_); #endif int attempts = 0; const int max_attempts = pardiso_iterative_ ? pardiso_max_droptol_corrections_+1: 1; while (attempts < max_attempts) { #ifdef PARDISO_MATCHING_PREPROCESS for (int i = 0; i < N; i++) { rhs_vals[perm2[i]] = scale2[i] * ORIG_RHS[ i ]; } PARDISO_FUNC(PT_, &MAXFCT_, &MNUM_, &MTYPE_, &PHASE, &N, a2_, ia2, ja2, &PERM, &NRHS, IPARM_, &MSGLVL_, rhs_vals, X, &ERROR, DPARM_); for (int i = 0; i < N; i++) { X[i] = rhs_vals[ perm2[i]]; } for (int i = 0; i < N; i++) { rhs_vals[i] = scale2[i]*X[i]; } #else for (int i = 0; i < N; i++) { rhs_vals[i] = ORIG_RHS[i]; } PARDISO_FUNC(PT_, &MAXFCT_, &MNUM_, &MTYPE_, &PHASE, &N, a_, ia, ja, &PERM, &NRHS, IPARM_, &MSGLVL_, rhs_vals, X, &ERROR, DPARM_); #endif if (ERROR <= -100 && ERROR >= -102) { Jnlst().Printf(J_WARNING, J_LINEAR_ALGEBRA, "Iterative solver in Pardiso did not converge (ERROR = %d)\n", ERROR); Jnlst().Printf(J_WARNING, J_LINEAR_ALGEBRA, " Decreasing drop tolerances from DPARM_[41] = %e and DPARM_[44] = %e\n", DPARM_[41], DPARM_[44]); PHASE = 23; DPARM_[4] /= 2.0 ; DPARM_[5] /= 2.0 ; Jnlst().Printf(J_WARNING, J_LINEAR_ALGEBRA, " to DPARM_[41] = %e and DPARM_[44] = %e\n", DPARM_[41], DPARM_[44]); attempts++; ERROR = 0; } else { attempts = max_attempts; // TODO we could try again with some PARDISO parameters changed, i.e., enabling iterative refinement } } delete [] X; delete [] ORIG_RHS; if (IPARM_[6] != 0) { Jnlst().Printf(J_DETAILED, J_LINEAR_ALGEBRA, "Number of iterative refinement steps = %d.\n", IPARM_[6]); if (HaveIpData()) { IpData().Append_info_string("Pi"); } } if (HaveIpData()) { IpData().TimingStats().LinearSystemBackSolve().End(); } if (ERROR!=0 ) { Jnlst().Printf(J_ERROR, J_LINEAR_ALGEBRA, "Error in Pardiso during solve phase. ERROR = %d.\n", ERROR); return SYMSOLVER_FATAL_ERROR; } return SYMSOLVER_SUCCESS; }
ESymSolverStatus Ma57TSolverInterface::SymbolicFactorization(const Index* airn, const Index* ajcn) { DBG_START_METH("Ma57TSolverInterface::SymbolicFactorization",dbg_verbosity); if (HaveIpData()) { IpData().TimingStats().LinearSystemSymbolicFactorization().Start(); } ipfint n = dim_; ipfint ne = nonzeros_; wd_lkeep_ = 5*n + ne + Max (n,ne) + 42; wd_cntl_[1-1] = pivtol_; /* Pivot threshold. */ wd_iwork_ = new ipfint[5*n]; wd_keep_ = new ipfint[wd_lkeep_]; // Initialize to 0 as otherwise MA57ED can sometimes fail for (int k=0; k<wd_lkeep_; k++) { wd_keep_[k] = 0; } F77_FUNC (ma57ad, MA57AD) (&n, &ne, airn, ajcn, &wd_lkeep_, wd_keep_, wd_iwork_, wd_icntl_, wd_info_, wd_rinfo_); if (wd_info_[0] < 0) { Jnlst().Printf(J_ERROR, J_LINEAR_ALGEBRA, "*** Error from MA57AD *** INFO(0) = %d\n", wd_info_[0]); } wd_lfact_ = (ipfint)((Number)wd_info_[8] * ma57_pre_alloc_); wd_lifact_ = (ipfint)((Number)wd_info_[9] * ma57_pre_alloc_); // XXX MH: Why is this necessary? Is `::Factorization' called more // than once per object lifetime? Where should allocation take // place, then? // AW: I moved this here now - my understanding is that wd_info[8] // and wd_info[9] are computed here, so we can just allocate the // amount of memory here. I don't think there is any need to // reallocate it later for every factorization delete [] wd_fact_; wd_fact_ = NULL; delete [] wd_ifact_; wd_ifact_ = NULL; wd_fact_ = new double[wd_lfact_]; wd_ifact_ = new int[wd_lifact_]; Jnlst().Printf(J_DETAILED, J_LINEAR_ALGEBRA, "Suggested lfact (*%e): %d\n", ma57_pre_alloc_, wd_lfact_); Jnlst().Printf(J_DETAILED, J_LINEAR_ALGEBRA, "Suggested lifact (*%e): %d\n", ma57_pre_alloc_, wd_lifact_); if (HaveIpData()) { IpData().TimingStats().LinearSystemSymbolicFactorization().End(); } return SYMSOLVER_SUCCESS; }
ESymSolverStatus WsmpSolverInterface:: DetermineDependentRows(const Index* ia, const Index* ja, std::list<Index>& c_deps) { DBG_START_METH("WsmpSolverInterface::DetermineDependentRows", dbg_verbosity); c_deps.clear(); ASSERT_EXCEPTION(!wsmp_no_pivoting_, OPTION_INVALID, "WSMP dependency detection does not work without pivoting."); if (!have_symbolic_factorization_) { ESymSolverStatus retval = InternalSymFact(ia, ja, 0); if (retval != SYMSOLVER_SUCCESS) { return retval; } have_symbolic_factorization_ = true; } // Call WSSMP for numerical factorization to detect degenerate // rows/columns ipfint N = dim_; ipfint NAUX = 0; IPARM_[1] = 3; // numerical factorization IPARM_[2] = 3; // numerical factorization DPARM_[10] = wsmp_pivtol_; // set current pivot tolerance ipfint idmy; double ddmy; #ifdef PARDISO_MATCHING_PREPROCESS F77_FUNC(wssmp,WSSMP)(&N, ia2, ja2, a2_, &ddmy, PERM_, INVP_, &ddmy, &idmy, &idmy, &ddmy, &NAUX, MRP_, IPARM_, DPARM_); #else F77_FUNC(wssmp,WSSMP)(&N, ia, ja, a_, &ddmy, PERM_, INVP_, &ddmy, &idmy, &idmy, &ddmy, &NAUX, MRP_, IPARM_, DPARM_); #endif const Index ierror = IPARM_[63]; if (ierror == 0) { int ii = 0; for (int i=0; i<N; i++) { if (MRP_[i] == -1) { c_deps.push_back(i); ii++; } } DBG_ASSERT(ii == IPARM_[20]); } if (ierror > 0) { Jnlst().Printf(J_DETAILED, J_LINEAR_ALGEBRA, "WSMP detected that the matrix is singular and encountered %d zero pivots.\n", dim_+1-ierror); if (HaveIpData()) { IpData().TimingStats().LinearSystemFactorization().End(); } return SYMSOLVER_SINGULAR; } else if (ierror != 0) { if (ierror == -102) { Jnlst().Printf(J_ERROR, J_LINEAR_ALGEBRA, "Error: WSMP is not able to allocate sufficient amount of memory during factorization.\n"); } else { Jnlst().Printf(J_ERROR, J_LINEAR_ALGEBRA, "Error in WSMP during factorization phase.\n Error code is %d.\n", ierror); } if (HaveIpData()) { IpData().TimingStats().LinearSystemFactorization().End(); } return SYMSOLVER_FATAL_ERROR; } return SYMSOLVER_SUCCESS; }
ESymSolverStatus WsmpSolverInterface::Solve( const Index* ia, const Index* ja, Index nrhs, double *rhs_vals) { DBG_START_METH("WsmpSolverInterface::Solve",dbg_verbosity); if (HaveIpData()) { IpData().TimingStats().LinearSystemBackSolve().Start(); } // Call WSMP to solve for some right hand sides (including // iterative refinement) // ToDo: Make iterative refinement an option? ipfint N = dim_; ipfint LDB = dim_; ipfint NRHS = nrhs; ipfint NAUX = 0; IPARM_[1] = 4; // Forward and Backward Elimintation IPARM_[2] = 5; // Iterative refinement IPARM_[5] = 1; DPARM_[5] = 1e-12; double ddmy; Jnlst().Printf(J_MOREDETAILED, J_LINEAR_ALGEBRA, "Calling WSSMP-4-5 for backsolve at cpu time %10.3f (wall %10.3f).\n", CpuTime(), WallclockTime()); #ifdef PARDISO_MATCHING_PREPROCESS double* X = new double[nrhs*N]; // Initialize solution with zero and save right hand side for (int i = 0; i < nrhs*N; i++) { X[perm2[i]] = scale2[i] * rhs_vals[i]; } F77_FUNC(wssmp,WSSMP)(&N, ia, ja, a_, &ddmy, PERM_, INVP_, X, &LDB, &NRHS, &ddmy, &NAUX, MRP_, IPARM_, DPARM_); for (int i = 0; i < N; i++) { rhs_vals[i] = scale2[i]*X[perm2[i]]; } #else F77_FUNC(wssmp,WSSMP)(&N, ia, ja, a_, &ddmy, PERM_, INVP_, rhs_vals, &LDB, &NRHS, &ddmy, &NAUX, MRP_, IPARM_, DPARM_); #endif Jnlst().Printf(J_MOREDETAILED, J_LINEAR_ALGEBRA, "Done with WSSMP-4-5 for backsolve at cpu time %10.3f (wall %10.3f).\n", CpuTime(), WallclockTime()); if (HaveIpData()) { IpData().TimingStats().LinearSystemBackSolve().End(); } Index ierror = IPARM_[63]; if (ierror!=0) { if (ierror==-102) { Jnlst().Printf(J_ERROR, J_LINEAR_ALGEBRA, "Error: WSMP is not able to allocate sufficient amount of memory during ordering/symbolic factorization.\n"); } else { Jnlst().Printf(J_ERROR, J_LINEAR_ALGEBRA, "Error in WSMP during ordering/symbolic factorization phase.\n Error code is %d.\n", ierror); } return SYMSOLVER_FATAL_ERROR; } Jnlst().Printf(J_DETAILED, J_LINEAR_ALGEBRA, "Number of iterative refinement steps in WSSMP: %d\n", IPARM_[5]); #ifdef PARDISO_MATCHING_PREPROCESS delete [] X; #endif return SYMSOLVER_SUCCESS; }
/* Method for initializing internal stuctures. Here, ndim gives * the number of rows and columns of the matrix, nonzeros give * the number of nonzero elements, and ia and ja give the * positions of the nonzero elements, given in the matrix format * determined by MatrixFormat. */ ESymSolverStatus Ma86SolverInterface::InitializeStructure(Index dim, Index nonzeros, const Index* ia, const Index* ja) { struct ma86_info info, info2; struct mc68_control control68; struct mc68_info info68; Index *order_amd, *order_metis; void *keep_amd, *keep_metis; // Store size for later use ndim_ = dim; // Determine an ordering mc68_default_control(&control68); control68.f_array_in = 1; // Use Fortran numbering (faster) control68.f_array_out = 1; // Use Fortran numbering (faster) order_amd = NULL; order_metis = NULL; if(ordering_ == ORDER_METIS || ordering_ == ORDER_AUTO) { order_metis = new Index[dim]; mc68_order(3, dim, ia, ja, order_metis, &control68, &info68); /* MeTiS */ if(info68.flag == -5) { // MeTiS not available ordering_ = ORDER_AMD; delete[] order_metis; } else if(info68.flag<0) { return SYMSOLVER_FATAL_ERROR; } } if(ordering_ == ORDER_AMD || ordering_ == ORDER_AUTO) { order_amd = new Index[dim]; mc68_order(1, dim, ia, ja, order_amd, &control68, &info68); /* AMD */ } if(info68.flag<0) return SYMSOLVER_FATAL_ERROR; if (HaveIpData()) { IpData().TimingStats().LinearSystemSymbolicFactorization().Start(); } // perform analyse if(ordering_ == ORDER_AUTO) { ma86_analyse(dim, ia, ja, order_amd, &keep_amd, &control_, &info2); if (info2.flag<0) return SYMSOLVER_FATAL_ERROR; ma86_analyse(dim, ia, ja, order_metis, &keep_metis, &control_, &info); if (info.flag<0) return SYMSOLVER_FATAL_ERROR; if(info.num_flops > info2.num_flops) { // Use AMD //cout << "Choose AMD\n"; order_ = order_amd; keep_ = keep_amd; delete[] order_metis; ma86_finalise(&keep_metis, &control_); } else { // Use MeTiS //cout << "Choose MeTiS\n"; order_ = order_metis; keep_ = keep_metis; delete[] order_amd; ma86_finalise(&keep_amd, &control_); } } else { if(ordering_ == ORDER_AMD) order_ = order_amd; if(ordering_ == ORDER_METIS) order_ = order_metis; ma86_analyse(dim, ia, ja, order_, &keep_, &control_, &info); } if (HaveIpData()) { IpData().TimingStats().LinearSystemSymbolicFactorization().End(); } // Setup memory for values if (val_!=NULL) delete[] val_; val_ = new double[nonzeros]; if (info.flag>=0) { return SYMSOLVER_SUCCESS; } else { return SYMSOLVER_FATAL_ERROR; } }
// Initialize the local copy of the positions of the nonzero // elements ESymSolverStatus TSymLinearSolver::InitializeStructure(const SymMatrix& sym_A) { DBG_START_METH("TSymLinearSolver::InitializeStructure", dbg_verbosity); DBG_ASSERT(!initialized_); ESymSolverStatus retval; // have_structure_ is already true if this is a warm start for a // problem with identical structure if (!have_structure_) { dim_ = sym_A.Dim(); nonzeros_triplet_ = TripletHelper::GetNumberEntries(sym_A); delete [] airn_; delete [] ajcn_; airn_ = new Index[nonzeros_triplet_]; ajcn_ = new Index[nonzeros_triplet_]; TripletHelper::FillRowCol(nonzeros_triplet_, sym_A, airn_, ajcn_); // If the solver wants the compressed format, the converter has to // be initialized const Index *ia; const Index *ja; Index nonzeros; if (matrix_format_ == SparseSymLinearSolverInterface::Triplet_Format) { ia = airn_; ja = ajcn_; nonzeros = nonzeros_triplet_; } else { if (HaveIpData()) { IpData().TimingStats().LinearSystemStructureConverter().Start(); IpData().TimingStats().LinearSystemStructureConverterInit().Start(); } nonzeros_compressed_ = triplet_to_csr_converter_->InitializeConverter(dim_, nonzeros_triplet_, airn_, ajcn_); if (HaveIpData()) { IpData().TimingStats().LinearSystemStructureConverterInit().End(); } ia = triplet_to_csr_converter_->IA(); ja = triplet_to_csr_converter_->JA(); if (HaveIpData()) { IpData().TimingStats().LinearSystemStructureConverter().End(); } nonzeros = nonzeros_compressed_; } retval = solver_interface_->InitializeStructure(dim_, nonzeros, ia, ja); if (retval != SYMSOLVER_SUCCESS) { return retval; } // Get space for the scaling factors delete [] scaling_factors_; if (IsValid(scaling_method_)) { if (HaveIpData()) { IpData().TimingStats().LinearSystemScaling().Start(); } scaling_factors_ = new double[dim_]; if (HaveIpData()) { IpData().TimingStats().LinearSystemScaling().End(); } } have_structure_ = true; } else { ASSERT_EXCEPTION(dim_==sym_A.Dim(), INVALID_WARMSTART, "TSymLinearSolver called with warm_start_same_structure, but the problem is solved for the first time."); // This is a warm start for identical structure, so we don't need to // recompute the nonzeros location arrays const Index *ia; const Index *ja; Index nonzeros; if (matrix_format_ == SparseSymLinearSolverInterface::Triplet_Format) { ia = airn_; ja = ajcn_; nonzeros = nonzeros_triplet_; } else { IpData().TimingStats().LinearSystemStructureConverter().Start(); ia = triplet_to_csr_converter_->IA(); ja = triplet_to_csr_converter_->JA(); IpData().TimingStats().LinearSystemStructureConverter().End(); nonzeros = nonzeros_compressed_; } retval = solver_interface_->InitializeStructure(dim_, nonzeros, ia, ja); } initialized_=true; return retval; }
bool TSymLinearSolver::InitializeImpl(const OptionsList& options, const std::string& prefix) { if (IsValid(scaling_method_)) { options.GetBoolValue("linear_scaling_on_demand", linear_scaling_on_demand_, prefix); } else { linear_scaling_on_demand_ = false; } // This option is registered by OrigIpoptNLP options.GetBoolValue("warm_start_same_structure", warm_start_same_structure_, prefix); bool retval; if (HaveIpData()) { retval = solver_interface_->Initialize(Jnlst(), IpNLP(), IpData(), IpCq(), options, prefix); } else { retval = solver_interface_->ReducedInitialize(Jnlst(), options, prefix); } if (!retval) { return false; } if (!warm_start_same_structure_) { // Reset all private data atag_=TaggedObject::Tag(); dim_=0; nonzeros_triplet_=0; nonzeros_compressed_=0; have_structure_=false; matrix_format_ = solver_interface_->MatrixFormat(); switch (matrix_format_) { case SparseSymLinearSolverInterface::CSR_Format_0_Offset: triplet_to_csr_converter_ = new TripletToCSRConverter(0); break; case SparseSymLinearSolverInterface::CSR_Format_1_Offset: triplet_to_csr_converter_ = new TripletToCSRConverter(1); break; case SparseSymLinearSolverInterface::CSR_Full_Format_0_Offset: triplet_to_csr_converter_ = new TripletToCSRConverter(0, TripletToCSRConverter::Full_Format); break; case SparseSymLinearSolverInterface::CSR_Full_Format_1_Offset: triplet_to_csr_converter_ = new TripletToCSRConverter(1, TripletToCSRConverter::Full_Format); break; case SparseSymLinearSolverInterface::Triplet_Format: triplet_to_csr_converter_ = NULL; break; default: DBG_ASSERT(false && "Invalid MatrixFormat returned from solver interface."); return false; } } else { ASSERT_EXCEPTION(have_structure_, INVALID_WARMSTART, "TSymLinearSolver called with warm_start_same_structure, but the internal structures are not initialized."); } // reset the initialize flag to make sure that InitializeStructure // is called for the linear solver initialized_=false; if (IsValid(scaling_method_) && !linear_scaling_on_demand_) { use_scaling_ = true; } else { use_scaling_ = false; } just_switched_on_scaling_ = false; if (IsValid(scaling_method_)) { if (HaveIpData()) { IpData().TimingStats().LinearSystemScaling().Start(); retval = scaling_method_->Initialize(Jnlst(), IpNLP(), IpData(), IpCq(), options, prefix); IpData().TimingStats().LinearSystemScaling().End(); } else { retval = scaling_method_->ReducedInitialize(Jnlst(), options, prefix); } } return retval; }
ESymSolverStatus PardisoSolverInterface::Factorization(const Index* ia, const Index* ja, bool check_NegEVals, Index numberOfNegEVals) { DBG_START_METH("PardisoSolverInterface::Factorization",dbg_verbosity); // Call Pardiso to do the factorization ipfint PHASE ; ipfint N = dim_; ipfint PERM; // This should not be accessed by Pardiso ipfint NRHS = 0; double B; // This should not be accessed by Pardiso in factorization // phase double X; // This should not be accessed by Pardiso in factorization // phase ipfint ERROR; bool done = false; bool just_performed_symbolic_factorization = false; while (!done) { if (!have_symbolic_factorization_) { if (HaveIpData()) { IpData().TimingStats().LinearSystemSymbolicFactorization().Start(); } PHASE = 11; #ifdef PARDISO_MATCHING_PREPROCESS delete[] ia2; ia2 = NULL; delete[] ja2; ja2 = NULL; delete[] a2_; a2_ = NULL; delete[] perm2; perm2 = NULL; delete[] scale2; scale2 = NULL; ia2 = new ipfint[N+1]; ja2 = new ipfint[nonzeros_]; a2_ = new double[nonzeros_]; perm2 = new ipfint[N]; scale2 = new double[N]; ipfint* tmp2_ = new ipfint[N]; smat_reordering_pardiso_wsmp_(&N, ia, ja, a_, ia2, ja2, a2_, perm2, scale2, tmp2_, 0); delete[] tmp2_; #endif Jnlst().Printf(J_DETAILED, J_LINEAR_ALGEBRA, "Calling Pardiso for symbolic factorization.\n"); PARDISO_FUNC(PT_, &MAXFCT_, &MNUM_, &MTYPE_, #ifdef PARDISO_MATCHING_PREPROCESS &PHASE, &N, a2_, ia2, ja2, &PERM, #else &PHASE, &N, a_, ia, ja, &PERM, #endif &NRHS, IPARM_, &MSGLVL_, &B, &X, &ERROR, DPARM_); if (HaveIpData()) { IpData().TimingStats().LinearSystemSymbolicFactorization().End(); } if (ERROR==-7) { Jnlst().Printf(J_MOREDETAILED, J_LINEAR_ALGEBRA, "Pardiso symbolic factorization returns ERROR = %d. Matrix is singular.\n", ERROR); return SYMSOLVER_SINGULAR; } else if (ERROR!=0) { Jnlst().Printf(J_ERROR, J_LINEAR_ALGEBRA, "Error in Pardiso during symbolic factorization phase. ERROR = %d.\n", ERROR); return SYMSOLVER_FATAL_ERROR; } have_symbolic_factorization_ = true; just_performed_symbolic_factorization = true; Jnlst().Printf(J_DETAILED, J_LINEAR_ALGEBRA, "Memory in KB required for the symbolic factorization = %d.\n", IPARM_[14]); Jnlst().Printf(J_DETAILED, J_LINEAR_ALGEBRA, "Integer memory in KB required for the numerical factorization = %d.\n", IPARM_[15]); Jnlst().Printf(J_DETAILED, J_LINEAR_ALGEBRA, "Double memory in KB required for the numerical factorization = %d.\n", IPARM_[16]); } PHASE = 22; if (HaveIpData()) { IpData().TimingStats().LinearSystemFactorization().Start(); } Jnlst().Printf(J_MOREDETAILED, J_LINEAR_ALGEBRA, "Calling Pardiso for factorization.\n"); // Dump matrix to file, and count number of solution steps. if (HaveIpData()) { if (IpData().iter_count() != debug_last_iter_) debug_cnt_ = 0; debug_last_iter_ = IpData().iter_count(); debug_cnt_ ++; } else { debug_cnt_ = 0; debug_last_iter_ = 0; } #ifdef PARDISO_MATCHING_PREPROCESS ipfint* tmp3_ = new ipfint[N]; smat_reordering_pardiso_wsmp_ (&N, ia, ja, a_, ia2, ja2, a2_, perm2, scale2, tmp3_, 1); delete[] tmp3_; #endif PARDISO_FUNC(PT_, &MAXFCT_, &MNUM_, &MTYPE_, #ifdef PARDISO_MATCHING_PREPROCESS &PHASE, &N, a2_, ia2, ja2, &PERM, #else &PHASE, &N, a_, ia, ja, &PERM, #endif &NRHS, IPARM_, &MSGLVL_, &B, &X, &ERROR, DPARM_); if (HaveIpData()) { IpData().TimingStats().LinearSystemFactorization().End(); } if (ERROR==-7) { Jnlst().Printf(J_MOREDETAILED, J_LINEAR_ALGEBRA, "Pardiso factorization returns ERROR = %d. Matrix is singular.\n", ERROR); return SYMSOLVER_SINGULAR; } else if (ERROR==-4) { // I think this means that the matrix is singular // OLAF said that this will never happen (ToDo) return SYMSOLVER_SINGULAR; } else if (ERROR!=0 ) { Jnlst().Printf(J_ERROR, J_LINEAR_ALGEBRA, "Error in Pardiso during factorization phase. ERROR = %d.\n", ERROR); return SYMSOLVER_FATAL_ERROR; } negevals_ = Max(IPARM_[22], numberOfNegEVals); if (IPARM_[13] != 0) { Jnlst().Printf(J_DETAILED, J_LINEAR_ALGEBRA, "Number of perturbed pivots in factorization phase = %d.\n", IPARM_[13]); if ( !pardiso_redo_symbolic_fact_only_if_inertia_wrong_ || (negevals_ != numberOfNegEVals) ) { if (HaveIpData()) { IpData().Append_info_string("Pn"); } have_symbolic_factorization_ = false; // We assume now that if there was just a symbolic // factorization and we still have perturbed pivots, that // the system is actually singular, if // pardiso_repeated_perturbation_means_singular_ is true if (just_performed_symbolic_factorization) { if (pardiso_repeated_perturbation_means_singular_) { if (HaveIpData()) { IpData().Append_info_string("Ps"); } return SYMSOLVER_SINGULAR; } else { done = true; } } else { done = false; } } else { if (HaveIpData()) { IpData().Append_info_string("Pp"); } done = true; } } else { done = true; } } DBG_ASSERT(IPARM_[21]+IPARM_[22] == dim_); // Check whether the number of negative eigenvalues matches the requested // count if (skip_inertia_check_) numberOfNegEVals=negevals_; if (check_NegEVals && (numberOfNegEVals!=negevals_)) { Jnlst().Printf(J_DETAILED, J_LINEAR_ALGEBRA, "Wrong inertia: required are %d, but we got %d.\n", numberOfNegEVals, negevals_); return SYMSOLVER_WRONG_INERTIA; } return SYMSOLVER_SUCCESS; }
ESymSolverStatus IterativePardisoSolverInterface::Solve(const Index* ia, const Index* ja, Index nrhs, double *rhs_vals) { DBG_START_METH("IterativePardisoSolverInterface::Solve",dbg_verbosity); DBG_ASSERT(nrhs==1); if (HaveIpData()) { IpData().TimingStats().LinearSystemBackSolve().Start(); } // Call Pardiso to do the solve for the given right-hand sides ipfint PHASE = 33; ipfint N = dim_; ipfint PERM; // This should not be accessed by Pardiso ipfint NRHS = nrhs; double* X = new double[nrhs*dim_]; double* ORIG_RHS = new double[nrhs*dim_]; ipfint ERROR; // Initialize solution with zero and save right hand side for (int i = 0; i < N; i++) { X[i] = 0; ORIG_RHS[i] = rhs_vals[i]; } // Dump matrix to file if requested Index iter_count = 0; if (HaveIpData()) { iter_count = IpData().iter_count(); } write_iajaa_matrix (N, ia, ja, a_, rhs_vals, iter_count, debug_cnt_); IterativeSolverTerminationTester* tester; int attempts = 0; const int max_attempts = pardiso_max_droptol_corrections_+1; bool is_normal = false; if (IsNull(InexData().normal_x()) && InexData().compute_normal()) { tester = GetRawPtr(normal_tester_); is_normal = true; } else { tester = GetRawPtr(pd_tester_); } global_tester_ptr_ = tester; while (attempts<max_attempts) { bool retval = tester->InitializeSolve(); ASSERT_EXCEPTION(retval, INTERNAL_ABORT, "tester->InitializeSolve(); returned false"); for (int i = 0; i < N; i++) { rhs_vals[i] = ORIG_RHS[i]; } DPARM_[ 8] = 25; // non_improvement in SQMR iteration F77_FUNC(pardiso,PARDISO)(PT_, &MAXFCT_, &MNUM_, &MTYPE_, &PHASE, &N, a_, ia, ja, &PERM, &NRHS, IPARM_, &MSGLVL_, rhs_vals, X, &ERROR, DPARM_); if (ERROR <= -100 && ERROR >= -110) { Jnlst().Printf(J_WARNING, J_LINEAR_ALGEBRA, "Iterative solver in Pardiso did not converge (ERROR = %d)\n", ERROR); Jnlst().Printf(J_WARNING, J_LINEAR_ALGEBRA, " Decreasing drop tolerances from DPARM_[ 4] = %e and DPARM_[ 5] = %e ", DPARM_[ 4], DPARM_[ 5]); if (is_normal) { Jnlst().Printf(J_WARNING, J_LINEAR_ALGEBRA, "(normal step)\n"); } else { Jnlst().Printf(J_WARNING, J_LINEAR_ALGEBRA, "(PD step)\n"); } PHASE = 23; DPARM_[ 4] *= decr_factor_; DPARM_[ 5] *= decr_factor_; Jnlst().Printf(J_WARNING, J_LINEAR_ALGEBRA, " to DPARM_[ 4] = %e and DPARM_[ 5] = %e\n", DPARM_[ 4], DPARM_[ 5]); // Copy solution back to y to get intial values for the next iteration attempts++; ERROR = 0; } else { attempts = max_attempts; Index iterations_used = tester->GetSolverIterations(); if (is_normal) { Jnlst().Printf(J_DETAILED, J_LINEAR_ALGEBRA, "Number of iterations in Pardiso iterative solver for normal step = %d.\n", iterations_used); } else { Jnlst().Printf(J_DETAILED, J_LINEAR_ALGEBRA, "Number of iterations in Pardiso iterative solver for PD step = %d.\n", iterations_used); } } tester->Clear(); } if (is_normal) { if (DPARM_[4] < normal_pardiso_iter_dropping_factor_) { Jnlst().Printf(J_DETAILED, J_LINEAR_ALGEBRA, "Increasing drop tolerances from DPARM_[ 4] = %e and DPARM_[ 5] = %e (normal step\n", DPARM_[ 4], DPARM_[ 5]); } normal_pardiso_iter_dropping_factor_used_ = Min(DPARM_[4]/decr_factor_, normal_pardiso_iter_dropping_factor_); normal_pardiso_iter_dropping_schur_used_ = Min(DPARM_[5]/decr_factor_, normal_pardiso_iter_dropping_schur_); if (DPARM_[4] < normal_pardiso_iter_dropping_factor_) { Jnlst().Printf(J_DETAILED, J_LINEAR_ALGEBRA, " to DPARM_[ 4] = %e and DPARM_[ 5] = %e for next iteration.\n", normal_pardiso_iter_dropping_factor_used_, normal_pardiso_iter_dropping_schur_used_); } } else { if (DPARM_[4] < pardiso_iter_dropping_factor_) { Jnlst().Printf(J_DETAILED, J_LINEAR_ALGEBRA, "Increasing drop tolerances from DPARM_[ 4] = %e and DPARM_[ 5] = %e (PD step\n", DPARM_[ 4], DPARM_[ 5]); } pardiso_iter_dropping_factor_used_ = Min(DPARM_[4]/decr_factor_, pardiso_iter_dropping_factor_); pardiso_iter_dropping_schur_used_ = Min(DPARM_[5]/decr_factor_, pardiso_iter_dropping_schur_); if (DPARM_[4] < pardiso_iter_dropping_factor_) { Jnlst().Printf(J_DETAILED, J_LINEAR_ALGEBRA, " to DPARM_[ 4] = %e and DPARM_[ 5] = %e for next iteration.\n", pardiso_iter_dropping_factor_used_, pardiso_iter_dropping_schur_used_); } } delete [] X; delete [] ORIG_RHS; if (IPARM_[6] != 0) { Jnlst().Printf(J_DETAILED, J_LINEAR_ALGEBRA, "Number of iterative refinement steps = %d.\n", IPARM_[6]); if (HaveIpData()) { IpData().Append_info_string("Pi"); } } if (HaveIpData()) { IpData().TimingStats().LinearSystemBackSolve().End(); } if (ERROR!=0 ) { Jnlst().Printf(J_ERROR, J_LINEAR_ALGEBRA, "Error in Pardiso during solve phase. ERROR = %d.\n", ERROR); return SYMSOLVER_FATAL_ERROR; } if (test_result_ == IterativeSolverTerminationTester::MODIFY_HESSIAN) { Jnlst().Printf(J_DETAILED, J_LINEAR_ALGEBRA, "Termination tester requests modification of Hessian\n"); return SYMSOLVER_WRONG_INERTIA; } #if 0 // FRANK: look at this: if (test_result_ == IterativeSolverTerminationTester::CONTINUE) { if (InexData().compute_normal()) { Jnlst().Printf(J_DETAILED, J_LINEAR_ALGEBRA, "Termination tester not satisfied!!! Pretend singular\n"); return SYMSOLVER_SINGULAR; } } #endif if (test_result_ == IterativeSolverTerminationTester::TEST_2_SATISFIED) { // Termination Test 2 is satisfied, set the step for the primal // iterates to zero Index nvars = IpData().curr()->x()->Dim() + IpData().curr()->s()->Dim(); const Number zero = 0.; IpBlasDcopy(nvars, &zero, 0, rhs_vals, 1); } return SYMSOLVER_SUCCESS; }
ESymSolverStatus IterativeWsmpSolverInterface::Factorization( const Index* ia, const Index* ja, bool check_NegEVals, Index numberOfNegEVals) { DBG_START_METH("IterativeWsmpSolverInterface::Factorization",dbg_verbosity); // If desired, write out the matrix Index iter_count = -1; if (HaveIpData()) { iter_count = IpData().iter_count(); } if (iter_count == wsmp_write_matrix_iteration_) { matrix_file_number_++; char buf[256]; Snprintf(buf, 255, "wsmp_matrix_%d_%d.dat", iter_count, matrix_file_number_); Jnlst().Printf(J_SUMMARY, J_LINEAR_ALGEBRA, "Writing WSMP matrix into file %s.\n", buf); FILE* fp = fopen(buf, "w"); fprintf(fp, "%d\n", dim_); // N for (Index icol=0; icol<dim_; icol++) { fprintf(fp, "%d", ia[icol+1]-ia[icol]); // number of elements for this column // Now for each colum we write row indices and values for (Index irow=ia[icol]; irow<ia[icol+1]; irow++) { fprintf(fp, " %23.16e %d",a_[irow-1],ja[irow-1]); } fprintf(fp, "\n"); } fclose(fp); } // Check if we have to do the symbolic factorization and ordering // phase yet if (!have_symbolic_factorization_) { ESymSolverStatus retval = InternalSymFact(ia, ja); if (retval != SYMSOLVER_SUCCESS) { return retval; } have_symbolic_factorization_ = true; } if (HaveIpData()) { IpData().TimingStats().LinearSystemFactorization().Start(); } // Call WSSMP for numerical factorization ipfint N = dim_; IPARM_[1] = 2; // value analysis IPARM_[2] = 3; // preconditioner generation DPARM_[10] = wsmp_pivtol_; // set current pivot tolerance ipfint idmy; double ddmy; // set drop tolerances for now.... if (wsmp_inexact_droptol_ != 0.) { DPARM_[13] = wsmp_inexact_droptol_; } if (wsmp_inexact_fillin_limit_ != 0.) { DPARM_[14] = wsmp_inexact_fillin_limit_; } Jnlst().Printf(J_MOREDETAILED, J_LINEAR_ALGEBRA, "Calling WISMP-2-3 with DPARM(14) = %8.2e and DPARM(15) = %8.2e.\n", DPARM_[13], DPARM_[14]); Jnlst().Printf(J_MOREDETAILED, J_LINEAR_ALGEBRA, "Calling WISMP-2-3 for value analysis and preconditioner computation at cpu time %10.3f (wall %10.3f).\n", CpuTime(), WallclockTime()); F77_FUNC(wismp,WISMP)(&N, ia, ja, a_, &ddmy, &idmy, &ddmy, &idmy, &idmy, &ddmy, &ddmy, IPARM_, DPARM_); Jnlst().Printf(J_MOREDETAILED, J_LINEAR_ALGEBRA, "Done with WISMP-2-3 for value analysis and preconditioner computation at cpu time %10.3f (wall %10.3f).\n", CpuTime(), WallclockTime()); Jnlst().Printf(J_MOREDETAILED, J_LINEAR_ALGEBRA, "Done with WISMP-2-3 with DPARM(14) = %8.2e and DPARM(15) = %8.2e.\n", DPARM_[13], DPARM_[14]); Jnlst().Printf(J_MOREDETAILED, J_LINEAR_ALGEBRA, " DPARM(4) = %8.2e and DPARM(5) = %8.2e and ratio = %8.2e.\n", DPARM_[3], DPARM_[4], DPARM_[3]/DPARM_[4]); const Index ierror = IPARM_[63]; if (ierror > 0) { Jnlst().Printf(J_DETAILED, J_LINEAR_ALGEBRA, "WISMP detected that the matrix is singular and encountered %d zero pivots.\n", dim_+1-ierror); if (HaveIpData()) { IpData().TimingStats().LinearSystemFactorization().End(); } return SYMSOLVER_SINGULAR; } else if (ierror != 0) { if (ierror == -102) { Jnlst().Printf(J_ERROR, J_LINEAR_ALGEBRA, "Error: WISMP is not able to allocate sufficient amount of memory during factorization.\n"); } else { Jnlst().Printf(J_ERROR, J_LINEAR_ALGEBRA, "Error in WSMP during factorization phase.\n Error code is %d.\n", ierror); } if (HaveIpData()) { IpData().TimingStats().LinearSystemFactorization().End(); } return SYMSOLVER_FATAL_ERROR; } Jnlst().Printf(J_DETAILED, J_LINEAR_ALGEBRA, "Memory usage for WISMP after factorization IPARM(23) = %d\n", IPARM_[22]); #if 0 // Check whether the number of negative eigenvalues matches the requested // count if (check_NegEVals && (numberOfNegEVals!=negevals_)) { Jnlst().Printf(J_DETAILED, J_LINEAR_ALGEBRA, "Wrong inertia: required are %d, but we got %d.\n", numberOfNegEVals, negevals_); if (HaveIpData()) { IpData().TimingStats().LinearSystemFactorization().End(); } return SYMSOLVER_WRONG_INERTIA; } #endif if (HaveIpData()) { IpData().TimingStats().LinearSystemFactorization().End(); } return SYMSOLVER_SUCCESS; }
ESymSolverStatus TSymLinearSolver::MultiSolve(const SymMatrix& sym_A, std::vector<SmartPtr<const Vector> >& rhsV, std::vector<SmartPtr<Vector> >& solV, bool check_NegEVals, Index numberOfNegEVals) { DBG_START_METH("TSymLinearSolver::MultiSolve",dbg_verbosity); DBG_ASSERT(!check_NegEVals || ProvidesInertia()); // Check if this object has ever seen a matrix If not, // allocate memory of the matrix structure and copy the nonzeros // structure (it is assumed that this will never change). if (!initialized_) { ESymSolverStatus retval = InitializeStructure(sym_A); if (retval != SYMSOLVER_SUCCESS) { return retval; } } DBG_ASSERT(nonzeros_triplet_== TripletHelper::GetNumberEntries(sym_A)); // Check if the matrix has been changed DBG_PRINT((1,"atag_=%d sym_A->GetTag()=%d\n",atag_,sym_A.GetTag())); bool new_matrix = sym_A.HasChanged(atag_); atag_ = sym_A.GetTag(); // If a new matrix is encountered, get the array for storing the // entries from the linear solver interface, fill in the new // values, compute the new scaling factors (if required), and // scale the matrix if (new_matrix || just_switched_on_scaling_) { GiveMatrixToSolver(true, sym_A); new_matrix = true; } // Retrieve the right hand sides and scale if required Index nrhs = (Index)rhsV.size(); double* rhs_vals = new double[dim_*nrhs]; for (Index irhs=0; irhs<nrhs; irhs++) { TripletHelper::FillValuesFromVector(dim_, *rhsV[irhs], &rhs_vals[irhs*(dim_)]); if (Jnlst().ProduceOutput(J_MOREMATRIX, J_LINEAR_ALGEBRA)) { Jnlst().Printf(J_MOREMATRIX, J_LINEAR_ALGEBRA, "Right hand side %d in TSymLinearSolver:\n", irhs); for (Index i=0; i<dim_; i++) { Jnlst().Printf(J_MOREMATRIX, J_LINEAR_ALGEBRA, "Trhs[%5d,%5d] = %23.16e\n", irhs, i, rhs_vals[irhs*(dim_)+i]); } } if (use_scaling_) { if (HaveIpData()) { IpData().TimingStats().LinearSystemScaling().Start(); } for (Index i=0; i<dim_; i++) { rhs_vals[irhs*(dim_)+i] *= scaling_factors_[i]; } if (HaveIpData()) { IpData().TimingStats().LinearSystemScaling().End(); } } } bool done = false; // Call the linear solver through the interface to solve the // system. This is repeated, if the return values is S_CALL_AGAIN // after the values have been restored (this might be necessary // for MA27 if the size of the work space arrays was not large // enough). ESymSolverStatus retval; while (!done) { const Index* ia; const Index* ja; if (matrix_format_==SparseSymLinearSolverInterface::Triplet_Format) { ia = airn_; ja = ajcn_; } else { if (HaveIpData()) { IpData().TimingStats().LinearSystemStructureConverter().Start(); } ia = triplet_to_csr_converter_->IA(); ja = triplet_to_csr_converter_->JA(); if (HaveIpData()) { IpData().TimingStats().LinearSystemStructureConverter().End(); } } retval = solver_interface_->MultiSolve(new_matrix, ia, ja, nrhs, rhs_vals, check_NegEVals, numberOfNegEVals); if (retval==SYMSOLVER_CALL_AGAIN) { DBG_PRINT((1, "Solver interface asks to be called again.\n")); GiveMatrixToSolver(false, sym_A); } else { done = true; } } // If the solve was successful, unscale the solution (if required) // and transfer the result into the Vectors if (retval==SYMSOLVER_SUCCESS) { for (Index irhs=0; irhs<nrhs; irhs++) { if (use_scaling_) { if (HaveIpData()) { IpData().TimingStats().LinearSystemScaling().Start(); } for (Index i=0; i<dim_; i++) { rhs_vals[irhs*(dim_)+i] *= scaling_factors_[i]; } if (HaveIpData()) { IpData().TimingStats().LinearSystemScaling().End(); } } if (Jnlst().ProduceOutput(J_MOREMATRIX, J_LINEAR_ALGEBRA)) { Jnlst().Printf(J_MOREMATRIX, J_LINEAR_ALGEBRA, "Solution %d in TSymLinearSolver:\n", irhs); for (Index i=0; i<dim_; i++) { Jnlst().Printf(J_MOREMATRIX, J_LINEAR_ALGEBRA, "Tsol[%5d,%5d] = %23.16e\n", irhs, i, rhs_vals[irhs*(dim_)+i]); } } TripletHelper::PutValuesInVector(dim_, &rhs_vals[irhs*(dim_)], *solV[irhs]); } } delete[] rhs_vals; return retval; }
ESymSolverStatus WsmpSolverInterface::InternalSymFact( const Index* ia, const Index* ja, Index numberOfNegEVals) { if (HaveIpData()) { IpData().TimingStats().LinearSystemSymbolicFactorization().Start(); } // Create space for the permutations delete [] PERM_; PERM_ = NULL; delete [] INVP_; INVP_ = NULL; delete [] MRP_; MRP_ = NULL; PERM_ = new ipfint[dim_]; INVP_ = new ipfint[dim_]; MRP_ = new ipfint[dim_]; ipfint N = dim_; #ifdef PARDISO_MATCHING_PREPROCESS delete[] ia2; ia2 = NULL; delete[] ja2; ja2 = NULL; delete[] a2_; a2_ = NULL; delete[] perm2; perm2 = NULL; delete[] scale2; scale2 = NULL; ia2 = new ipfint[N+1]; ja2 = new ipfint[nonzeros_]; a2_ = new double[nonzeros_]; perm2 = new ipfint[N]; scale2 = new double[N]; ipfint* tmp2_ = new ipfint[N]; smat_reordering_pardiso_wsmp_(&N, ia, ja, a_, ia2, ja2, a2_, perm2, scale2, tmp2_, 0); delete[] tmp2_; #endif // Call WSSMP for ordering and symbolic factorization ipfint NAUX = 0; IPARM_[1] = 1; // ordering IPARM_[2] = 2; // symbolic factorization #ifdef PARDISO_MATCHING_PREPROCESS IPARM_[9] = 2; // switch off WSMP's ordering and scaling IPARM_[15] = -1; // switch off WSMP's ordering and scaling IPARM_[30] = 6; // next step supernode pivoting , since not implemented // =2 regular Bunch/Kaufman // =1 no pivots // =6 limited pivots DPARM_[21] = 2e-8; // set pivot perturbation #endif ipfint idmy; double ddmy; if (wsmp_no_pivoting_) { IPARM_[14] = dim_ - numberOfNegEVals; // CHECK Jnlst().Printf(J_MOREDETAILED, J_LINEAR_ALGEBRA, "Restricting WSMP static pivot sequence with IPARM(15) = %d\n", IPARM_[14]); } Jnlst().Printf(J_MOREDETAILED, J_LINEAR_ALGEBRA, "Calling WSSMP-1-2 for ordering and symbolic factorization at cpu time %10.3f (wall %10.3f).\n", CpuTime(), WallclockTime()); #ifdef PARDISO_MATCHING_PREPROCESS F77_FUNC(wssmp,WSSMP)(&N, ia2, ja2, a2_, &ddmy, PERM_, INVP_, #else F77_FUNC(wssmp,WSSMP)(&N, ia, ja, a_, &ddmy, PERM_, INVP_, #endif &ddmy, &idmy, &idmy, &ddmy, &NAUX, MRP_, IPARM_, DPARM_); Jnlst().Printf(J_MOREDETAILED, J_LINEAR_ALGEBRA, "Done with WSSMP-1-2 for ordering and symbolic factorization at cpu time %10.3f (wall %10.3f).\n", CpuTime(), WallclockTime()); Index ierror = IPARM_[63]; if (ierror!=0) { if (ierror==-102) { Jnlst().Printf(J_ERROR, J_LINEAR_ALGEBRA, "Error: WSMP is not able to allocate sufficient amount of memory during ordering/symbolic factorization.\n"); } else if (ierror>0) { Jnlst().Printf(J_DETAILED, J_LINEAR_ALGEBRA, "Matrix appears to be singular (with ierror = %d).\n", ierror); if (HaveIpData()) { IpData().TimingStats().LinearSystemSymbolicFactorization().End(); } return SYMSOLVER_SINGULAR; } else { Jnlst().Printf(J_ERROR, J_LINEAR_ALGEBRA, "Error in WSMP during ordering/symbolic factorization phase.\n Error code is %d.\n", ierror); } if (HaveIpData()) { IpData().TimingStats().LinearSystemSymbolicFactorization().End(); } return SYMSOLVER_FATAL_ERROR; } Jnlst().Printf(J_DETAILED, J_LINEAR_ALGEBRA, "Predicted memory usage for WSSMP after symbolic factorization IPARM(23)= %d.\n", IPARM_[22]); Jnlst().Printf(J_DETAILED, J_LINEAR_ALGEBRA, "Predicted number of nonzeros in factor for WSSMP after symbolic factorization IPARM(23)= %d.\n", IPARM_[23]); if (HaveIpData()) { IpData().TimingStats().LinearSystemSymbolicFactorization().End(); } return SYMSOLVER_SUCCESS; }