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 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; }