void MUMPS_solver::get_factorization( Mat<double, Gen<>, SparseLine<> > &mat, bool want_free ) { if ( already_factorized ) return; else already_factorized = true; init_MPI(); /// initialisation de MUMPS pour un seul processeur id.par = 1; /// le maître participe à la factorisation id.sym = 0; /// matrice générale id.comm_fortran = use_comm_word; /// communicator de MPI id.job = job_init; dmumps_c( &id ); id.ICNTL( 1 ) = -1; /*! No outputs */ id.ICNTL( 2 ) = -1; /*! No outputs */ id.ICNTL( 3 ) = -1; /*! No outputs */ id.ICNTL( 4 ) = -1; /*! No outputs */ /*! Define the problem on the host */ if ( myid == 0 ) { free(); /// construction des données nécessaires à la factorisation (excepté a qui peut ne pas être nécessaire ) load_matrix( mat ); id.job = job_analyse; dmumps_c( &id ); id.job = job_factorize; dmumps_c( &id ); if ( want_free ) mat.free(); } }
int MAIN__() { int argc = 1; char * name = "c_example"; char ** argv; #else int main(int argc, char ** argv) { #endif DMUMPS_STRUC_C id; MUMPS_INT n = 2; MUMPS_INT nz = 2; MUMPS_INT irn[] = { 1, 2 }; MUMPS_INT jcn[] = { 1, 2 }; double a[2]; double rhs[2]; MUMPS_INT myid, ierr; #if defined(MAIN_COMP) argv = &name; #endif ierr = MPI_Init(&argc, &argv); ierr = MPI_Comm_rank(MPI_COMM_WORLD, &myid); /* Define A and rhs */ rhs[0] = 1.0; rhs[1] = 4.0; a[0] = 1.0; a[1] = 2.0; /* Initialize a MUMPS instance. Use MPI_COMM_WORLD */ id.job = JOB_INIT; id.par = 1; id.sym = 0; id.comm_fortran = USE_COMM_WORLD; dmumps_c(&id); /* Define the problem on the host */ if (myid == 0) { id.n = n; id.nz = nz; id.irn = irn; id.jcn = jcn; id.a = a; id.rhs = rhs; } #define ICNTL(I) icntl[(I)-1] /* macro s.t. indices match documentation */ /* No outputs */ id.ICNTL(1) = -1; id.ICNTL(2) = -1; id.ICNTL(3) = -1; id.ICNTL(4) = 0; /* Call the MUMPS package. */ id.job = 6; dmumps_c(&id); id.job = JOB_END; dmumps_c(&id); /* Terminate instance */ if (myid == 0) { printf("Solution is : (%8.2f %8.2f)\n", rhs[0], rhs[1]); } ierr = MPI_Finalize(); getchar(); return 0; }
//------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- ClpCholeskyMumps::ClpCholeskyMumps (int denseThreshold) : ClpCholeskyBase(denseThreshold) { mumps_ = (DMUMPS_STRUC_C*)malloc(sizeof(DMUMPS_STRUC_C)); type_ = 16; mumps_->n = 0; mumps_->nz = 0; mumps_->a = NULL; mumps_->jcn = NULL; mumps_->irn = NULL; mumps_->job = JOB_INIT;//initialize mumps mumps_->par = 1;//working host for sequential version mumps_->sym = 2;//general symmetric matrix mumps_->comm_fortran = USE_COMM_WORLD; int myid, ierr; int justName; ierr = MPI_Init(&justName, NULL); ierr = MPI_Comm_rank(MPI_COMM_WORLD, &myid); assert (!ierr); dmumps_c(mumps_); #define ICNTL(I) icntl[(I)-1] /* macro s.t. indices match documentation */ #define CNTL(I) cntl[(I)-1] /* macro s.t. indices match documentation */ mumps_->ICNTL(5) = 1; // say compressed format mumps_->ICNTL(4) = 2; // log messages mumps_->ICNTL(24) = 1; // Deal with zeros on diagonal mumps_->CNTL(3) = 1.0e-20; // drop if diagonal less than this // output off mumps_->ICNTL(1) = -1; mumps_->ICNTL(2) = -1; mumps_->ICNTL(3) = -1; mumps_->ICNTL(4) = 0; }
//============================================================================= void Amesos_Mumps::Destroy() { if (!NoDestroy_) { // destroy instance of the package MDS.job = -2; if (Comm().MyPID() < MaxProcs_) dmumps_c(&(MDS)); #if 0 if (IsComputeSchurComplementOK_ && (Comm().MyPID() == 0) && MDS.schur) { delete [] MDS.schur; MDS.schur = 0; } #endif #ifdef HAVE_MPI if (MUMPSComm_) { MPI_Comm_free( &MUMPSComm_ ); MUMPSComm_ = 0; } #endif if( (verbose_ && PrintTiming_) || verbose_ == 2) PrintTiming(); if( (verbose_ && PrintStatus_) || verbose_ == 2) PrintStatus(); } }
bool Chordal::solveSchur(Vector& rhs) { mumps_id.job = MUMPS_JOB_SOLVE; mumps_id.rhs = rhs.ele; dmumps_c(&mumps_id); return SDPA_SUCCESS; }
/* Uses factorization to solve. */ void ClpCholeskyMumps::solve (double * region) { mumps_->rhs = region; mumps_->job = 3; // solve dmumps_c(mumps_); }
//------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- ClpCholeskyMumps::~ClpCholeskyMumps () { mumps_->job = JOB_END; dmumps_c(mumps_); /* Terminate instance */ MPI_Finalize(); free(mumps_); }
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; }
MumpsSolverInterface::MumpsSolverInterface() { DBG_START_METH("MumpsSolverInterface::MumpsSolverInterface()", dbg_verbosity); //initialize mumps DMUMPS_STRUC_C* mumps_ = new DMUMPS_STRUC_C; int argc=1; char ** argv = 0; int myid; MPI_Init(&argc, &argv); MPI_Comm_rank(MPI_COMM_WORLD, &myid); mumps_->n = 0; mumps_->nz = 0; mumps_->a = NULL; mumps_->jcn = NULL; mumps_->irn = NULL; mumps_->job = -1;//initialize mumps mumps_->par = 1;//working host for sequential version mumps_->sym = 2;//general symetric matrix mumps_->comm_fortran = USE_COMM_WORLD; dmumps_c(mumps_); mumps_->icntl[1] = 0; mumps_->icntl[2] = 0;//QUIETLY! mumps_->icntl[3] = 0; mumps_ptr_ = (void*)mumps_; }
bool Chordal::factorizeSchur(int m, int* diagonalIndex, FILE* Display, FILE* fpOut) { // I need to adjust Schur before factorization // to loose Numerical Error Condition double adjustSize = PLUS_ADJUST_DIAGONAL; for (int i=0; i<m; ++i) { sparse_bMat_ptr->sp_ele[diagonalIndex[i]] += adjustSize; } mumps_id.job = MUMPS_JOB_FACTORIZE; mumps_id.a = sparse_bMat_ptr->sp_ele; dmumps_c(&mumps_id); bool isSuccess = SDPA_SUCCESS; while (mumps_id.infog[1-1] == -9) { #if 0 rMessage("mumps icntl(14) = " << mumps_id.icntl[14-1]); rMessage("mumps icntl(23) = " << mumps_id.icntl[23-1]); #endif if (Display) { fprintf(Display,"MUMPS needs more memory space. Trying ANALYSIS phase once more\n"); } if (fpOut) { fprintf(fpOut, "MUMPS needs more memory space. Trying ANALYSIS phase once more\n"); } mumps_id.icntl[14-1] += 20; // More 20% working memory space analysisAndcountLowerNonZero(m); mumps_id.job = MUMPS_JOB_FACTORIZE; dmumps_c(&mumps_id); } if (mumps_id.infog[1-1] < 0) { isSuccess = SDPA_FAILURE; if (mumps_id.infog[1-1] == -10) { rMessage("Cholesky failed by NUMERICAL ERROR"); rMessage("There are some possibilities."); rMessage("1. SDPA terminates due to inaccuracy of numerical error"); rMessage("2. The input problem may not have (any) interior-points"); rMessage("3. Input matrices are linearly dependent"); } else { rMessage("Cholesky failed with Error Code " << mumps_id.infog[1-1]); } } return isSuccess; }
MUMPS_solver::~MUMPS_solver() { if ( MPI_is_initialized ) { id.job = job_end; dmumps_c( &id ); /** Terminate instance */ ierr = MPI_Finalize(); //std::cerr << "MPI_Finalize() = " << ierr << std::endl; } }
void Chordal::terminate() { if (mumps_usage == true) { mumps_id.job = MUMPS_JOB_END; dmumps_c(&mumps_id); mumps_usage = false; } if (sparse_bMat_ptr) { sparse_bMat_ptr->terminate(); } sparse_bMat_ptr = NULL; }
MumpsSolverInterface::~MumpsSolverInterface() { DBG_START_METH("MumpsSolverInterface::~MumpsSolverInterface()", dbg_verbosity); DMUMPS_STRUC_C* mumps_ = (DMUMPS_STRUC_C*)mumps_ptr_; mumps_->job = -2; //terminate mumps dmumps_c(mumps_); MPI_Finalize(); delete [] mumps_->a; delete mumps_; }
void Chordal::initialize(SparseMatrix* sparse_bMat_ptr) { // condition of sparse computation // m_threshold < mDim, // b_threshold < nBlock, // aggregate_threshold >= aggrigated sparsity ratio // extend_threshold >= extended sparsity ratio m_threshold = 100; b_threshold = 5; aggregate_threshold = 0.70; extend_threshold = 0.80; #if FORCE_SCHUR_DENSE // DENSE computation for debugging m_threshold = 10000000; b_threshold = 1000000; aggregate_threshold = 0.0; extend_threshold = 0.0; #endif #if FORCE_SCHUR_SPARSE // SPARSE computation for debugging m_threshold = 0; b_threshold = 0; aggregate_threshold = 2.0; extend_threshold = 2.0; #endif // initialize by assuming Schur would be DENSE best = SELECT_DENSE; this->sparse_bMat_ptr = sparse_bMat_ptr; // initialize MUMPS mumps_id.job = MUMPS_JOB_INIT; mumps_id.comm_fortran = MUMPS_USE_COMM_WORLD; // rank 0 process participates factorizations mumps_id.par = 1; // Only symmetric positive definite matricies mumps_id.sym = 1; // No OUTPUTS mumps_id.icntl[1-1] = -1; mumps_id.icntl[2-1] = -1; mumps_id.icntl[3-1] = -1; mumps_id.icntl[4-1] = 0; // MUMPS selects ordering automatically mumps_id.icntl[7-1] = SELECT_MUMPS_BEST; // for Minumum Degree Ordering // mumps_id.icntl[7-1] = 0; dmumps_c(&mumps_id); mumps_usage = true; }
int Amesos_Mumps::NumericFactorization() { IsNumericFactorizationOK_ = false; if (IsSymbolicFactorizationOK_ == false) AMESOS_CHK_ERR(SymbolicFactorization()); RedistrMatrix(true); AMESOS_CHK_ERR(ConvertToTriplet(true)); if (Comm().NumProc() != 1) { if (Comm().MyPID() < MaxProcs_) MDS.a_loc = &Val[0]; } else MDS.a = &Val[0]; // Request numeric factorization MDS.job = 2; // Perform numeric factorization ResetTimer(); if (Comm().MyPID() < MaxProcs_) { dmumps_c(&(MDS)); } NumFactTime_ = AddTime("Total numeric factorization time", NumFactTime_); int IntWrong = CheckError()?1:0 ; int AnyWrong; Comm().SumAll( &IntWrong, &AnyWrong, 1 ) ; bool Wrong = AnyWrong > 0 ; if ( Wrong ) { AMESOS_CHK_ERR( NumericallySingularMatrixError ) ; } IsNumericFactorizationOK_ = true; NumNumericFact_++; return(0); }
double Chordal::analysisAndcountLowerNonZero(int m) { mumps_id.job = MUMPS_JOB_ANALYSIS; mumps_id.n = m; mumps_id.nz = sparse_bMat_ptr->NonZeroCount; mumps_id.irn = sparse_bMat_ptr->row_index; mumps_id.jcn = sparse_bMat_ptr->column_index; mumps_id.a = sparse_bMat_ptr->sp_ele; // sparse_bMat_ptr->display(); // rMessage("m = " << m); // rMessage("NonZeroCount = " << sparse_bMat_ptr->NonZeroCount); // No OUTPUTS for analysis mumps_id.icntl[1-1] = -1; mumps_id.icntl[2-1] = -1; mumps_id.icntl[3-1] = -1; mumps_id.icntl[4-1] = 0; // strcpy(mumps_id.write_problem,"write_problem"); dmumps_c(&mumps_id); double lower_nonzeros = (double)mumps_id.infog[20-1]; // if lower_nonzeros is greater than 1.0e+6, // the value infog[20-1] is lower_nonzeros*(-1)/(1.0e+6). // we need to adjust the value. if (lower_nonzeros < 0) { lower_nonzeros *= (-1.0e+6); } #if 0 rMessage("lower_nonzeros = " << lower_nonzeros); rMessage("Schur density = " << lower_nonzeros/((m+1)*m/2)*100 << "%" ); #endif if (mumps_id.infog[1-1] != 0) { rError("MUMPS ERROR " << mumps_id.infog[1-1]); } return lower_nonzeros; }
/* Orders rows and saves pointer to matrix.and model */ int ClpCholeskyMumps::order(ClpInterior * model) { numberRows_ = model->numberRows(); if (doKKT_) { numberRows_ += numberRows_ + model->numberColumns(); printf("finish coding MUMPS KKT!\n"); abort(); } rowsDropped_ = new char [numberRows_]; memset(rowsDropped_, 0, numberRows_); numberRowsDropped_ = 0; model_ = model; rowCopy_ = model->clpMatrix()->reverseOrderedCopy(); const CoinBigIndex * columnStart = model_->clpMatrix()->getVectorStarts(); const int * columnLength = model_->clpMatrix()->getVectorLengths(); const int * row = model_->clpMatrix()->getIndices(); const CoinBigIndex * rowStart = rowCopy_->getVectorStarts(); const int * rowLength = rowCopy_->getVectorLengths(); const int * column = rowCopy_->getIndices(); // We need two arrays for counts int * which = new int [numberRows_]; int * used = new int[numberRows_+1]; CoinZeroN(used, numberRows_); int iRow; sizeFactor_ = 0; for (iRow = 0; iRow < numberRows_; iRow++) { int number = 1; // make sure diagonal exists which[0] = iRow; used[iRow] = 1; if (!rowsDropped_[iRow]) { CoinBigIndex startRow = rowStart[iRow]; CoinBigIndex endRow = rowStart[iRow] + rowLength[iRow]; for (CoinBigIndex k = startRow; k < endRow; k++) { int iColumn = column[k]; CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = columnStart[iColumn] + columnLength[iColumn]; for (CoinBigIndex j = start; j < end; j++) { int jRow = row[j]; if (jRow >= iRow && !rowsDropped_[jRow]) { if (!used[jRow]) { used[jRow] = 1; which[number++] = jRow; } } } } sizeFactor_ += number; int j; for (j = 0; j < number; j++) used[which[j]] = 0; } } delete [] which; // NOT COMPRESSED FOR NOW ??? - Space for starts mumps_->ICNTL(5) = 0; // say NOT compressed format try { choleskyStart_ = new CoinBigIndex[numberRows_+1+sizeFactor_]; } catch (...) { // no memory return -1; } // Now we have size - create arrays and fill in try { choleskyRow_ = new int [sizeFactor_]; } catch (...) { // no memory delete [] choleskyStart_; choleskyStart_ = NULL; return -1; } try { sparseFactor_ = new double[sizeFactor_]; } catch (...) { // no memory delete [] choleskyRow_; choleskyRow_ = NULL; delete [] choleskyStart_; choleskyStart_ = NULL; return -1; } sizeFactor_ = 0; which = choleskyRow_; for (iRow = 0; iRow < numberRows_; iRow++) { int number = 1; // make sure diagonal exists which[0] = iRow; used[iRow] = 1; choleskyStart_[iRow] = sizeFactor_; if (!rowsDropped_[iRow]) { CoinBigIndex startRow = rowStart[iRow]; CoinBigIndex endRow = rowStart[iRow] + rowLength[iRow]; for (CoinBigIndex k = startRow; k < endRow; k++) { int iColumn = column[k]; CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = columnStart[iColumn] + columnLength[iColumn]; for (CoinBigIndex j = start; j < end; j++) { int jRow = row[j]; if (jRow >= iRow && !rowsDropped_[jRow]) { if (!used[jRow]) { used[jRow] = 1; which[number++] = jRow; } } } } sizeFactor_ += number; int j; for (j = 0; j < number; j++) used[which[j]] = 0; // Sort std::sort(which, which + number); // move which on which += number; } } choleskyStart_[numberRows_] = sizeFactor_; delete [] used; permuteInverse_ = new int [numberRows_]; permute_ = new int[numberRows_]; // To Fortran and fake for (iRow = 0; iRow < numberRows_ + 1; iRow++) { int k = choleskyStart_[iRow]; int kEnd = choleskyStart_[iRow+1]; k += numberRows_ + 1; kEnd += numberRows_ + 1; for (; k < kEnd; k++) choleskyStart_[k] = iRow + 1; choleskyStart_[iRow]++; } mumps_->nz = sizeFactor_; mumps_->irn = choleskyStart_ + numberRows_ + 1; mumps_->jcn = choleskyRow_; mumps_->a = NULL; for (CoinBigIndex i = 0; i < sizeFactor_; i++) { choleskyRow_[i]++; #ifndef NDEBUG assert (mumps_->irn[i] >= 1 && mumps_->irn[i] <= numberRows_); assert (mumps_->jcn[i] >= 1 && mumps_->jcn[i] <= numberRows_); #endif } // validate //mumps code here mumps_->n = numberRows_; mumps_->nelt = numberRows_; mumps_->eltptr = choleskyStart_; mumps_->eltvar = choleskyRow_; mumps_->a_elt = NULL; mumps_->rhs = NULL; mumps_->job = 1; // order dmumps_c(mumps_); mumps_->a = sparseFactor_; if (mumps_->infog[0]) { COIN_DETAIL_PRINT(printf("MUMPS ordering failed -error %d %d\n", mumps_->infog[0], mumps_->infog[1])); return 1; } else { double size = mumps_->infog[19]; if (size < 0) size *= -1000000; COIN_DETAIL_PRINT(printf("%g nonzeros, flop count %g\n", size, mumps_->rinfog[0])); } for (iRow = 0; iRow < numberRows_; iRow++) { permuteInverse_[iRow] = iRow; permute_[iRow] = iRow; } return 0; }
ESymSolverStatus MumpsSolverInterface:: DetermineDependentRows(const Index* ia, const Index* ja, std::list<Index>& c_deps) { DBG_START_METH("MumpsSolverInterface::DetermineDependentRows", dbg_verbosity); DMUMPS_STRUC_C* mumps_data = (DMUMPS_STRUC_C*)mumps_ptr_; c_deps.clear(); ESymSolverStatus retval; // Do the symbolic facotrization if it hasn't been done yet if (!have_symbolic_factorization_) { const Index mumps_permuting_scaling_orig = mumps_permuting_scaling_; const Index mumps_scaling_orig = mumps_scaling_; mumps_permuting_scaling_ = 0; mumps_scaling_ = 6; retval = SymbolicFactorization(); mumps_permuting_scaling_ = mumps_permuting_scaling_orig; mumps_scaling_ = mumps_scaling_orig; if (retval != SYMSOLVER_SUCCESS ) { return retval; } have_symbolic_factorization_ = true; } // perform the factorization, in order to find dependent rows/columns //Set flags to ask MUMPS for checking linearly dependent rows mumps_data->icntl[23] = 1; mumps_data->cntl[2] = mumps_dep_tol_; mumps_data->job = 2;//numerical factorization dump_matrix(mumps_data); dmumps_c(mumps_data); int error = mumps_data->info[0]; //Check for errors if (error == -8 || error == -9) {//not enough memory const Index trycount_max = 20; for (int trycount=0; trycount<trycount_max; trycount++) { Jnlst().Printf(J_WARNING, J_LINEAR_ALGEBRA, "MUMPS returned INFO(1) = %d and requires more memory, reallocating. Attempt %d\n", error,trycount+1); Jnlst().Printf(J_WARNING, J_LINEAR_ALGEBRA, " Increasing icntl[13] from %d to ", mumps_data->icntl[13]); double mem_percent = mumps_data->icntl[13]; mumps_data->icntl[13] = (Index)(2.0 * mem_percent); Jnlst().Printf(J_WARNING, J_LINEAR_ALGEBRA, "%d.\n", mumps_data->icntl[13]); dump_matrix(mumps_data); dmumps_c(mumps_data); error = mumps_data->info[0]; if (error != -8 && error != -9) break; } if (error == -8 || error == -9) { Jnlst().Printf(J_ERROR, J_LINEAR_ALGEBRA, "MUMPS was not able to obtain enough memory.\n"); // Reset flags mumps_data->icntl[23] = 0; return SYMSOLVER_FATAL_ERROR; } } // Reset flags mumps_data->icntl[23] = 0; if (error < 0) {//some other error Jnlst().Printf(J_ERROR, J_LINEAR_ALGEBRA, "MUMPS returned INFO(1) =%d MUMPS failure.\n", error); return SYMSOLVER_FATAL_ERROR; } const Index n_deps = mumps_data->infog[27]; for (Index i=0; i<n_deps; i++) { c_deps.push_back(mumps_data->pivnul_list[i]-1); } return SYMSOLVER_SUCCESS; }
DMUMPS_STRUC_C* NM_MUMPS_id(NumericsMatrix* A) { NumericsSparseLinearSolverParams* params = NM_linearSolverParams(A); if (!params->solver_data) { params->solver_data = malloc(sizeof(DMUMPS_STRUC_C)); DMUMPS_STRUC_C* mumps_id = (DMUMPS_STRUC_C*) params->solver_data; // Initialize a MUMPS instance. Use MPI_COMM_WORLD. mumps_id->job = JOB_INIT; mumps_id->par = 1; mumps_id->sym = 0; if (NM_MPI_com(A) == MPI_COMM_WORLD) { mumps_id->comm_fortran = USE_COMM_WORLD; } else { mumps_id->comm_fortran = MPI_Comm_c2f(NM_MPI_com(A)); } dmumps_c(mumps_id); if (verbose == 1) { mumps_id->ICNTL(1) = -1; // Error messages, standard output stream. mumps_id->ICNTL(2) = -1; // Diagnostics, standard output stream. mumps_id->ICNTL(3) = -1; // Global infos, standard output stream. mumps_id->ICNTL(11) = 1; // Error analysis } else if (verbose == 2) { mumps_id->ICNTL(1) = -1; // Error messages, standard output stream. mumps_id->ICNTL(2) = -1; // Diagnostics, standard output stream. mumps_id->ICNTL(3) = 6; // Global infos, standard output stream. // mumps_id->ICNTL(4) = 4; // Errors, warnings and information on // input, output parameters printed. // mumps_id->ICNTL(10) = 1; // One step of iterative refinment mumps_id->ICNTL(11) = 1; // Error analysis } else if (verbose >= 3) { mumps_id->ICNTL(1) = 6; // Error messages, standard output stream. mumps_id->ICNTL(2) = 6; // Diagnostics, standard output stream. mumps_id->ICNTL(3) = 6; // Global infos, standard output stream. // mumps_id->ICNTL(4) = 4; // Errors, warnings and information on // input, output parameters printed. // mumps_id->ICNTL(10) = 1; // One step of iterative refinment mumps_id->ICNTL(11) = 1; // Error analysis } else { mumps_id->ICNTL(1) = -1; mumps_id->ICNTL(2) = -1; mumps_id->ICNTL(3) = -1; } mumps_id->ICNTL(24) = 1; // Null pivot row detection see also CNTL(3) & CNTL(5) // ok for a cube on a plane & four contact points // computeAlartCurnierSTD != generated in this case... //mumps_id->CNTL(3) = ...; //mumps_id->CNTL(5) = ...; } DMUMPS_STRUC_C* mumps_id = (DMUMPS_STRUC_C*) params->solver_data; mumps_id->n = (int) NM_triplet(A)->n; mumps_id->irn = NM_MUMPS_irn(A); mumps_id->jcn = NM_MUMPS_jcn(A); int nz; if (NM_sparse(A)->triplet) { nz = (int) NM_sparse(A)->triplet->nz; mumps_id->nz = nz; mumps_id->a = NM_sparse(A)->triplet->x; } else { nz = NM_linearSolverParams(A)->iWork[2 * NM_csc(A)->nzmax]; mumps_id->nz = nz; mumps_id->a = NM_sparse(A)->csc->x; } return (DMUMPS_STRUC_C*) params->solver_data; }
int NM_gesv(NumericsMatrix* A, double *b) { assert(A->size0 == A->size1); int info = 1; switch (A->storageType) { case NM_DENSE: { assert(A->matrix0); DGESV(A->size0, 1, A->matrix0, A->size0, NM_iWork(A, A->size0), b, A->size0, &info); break; } case NM_SPARSE_BLOCK: /* sparse block -> triplet -> csc */ case NM_SPARSE: { switch (NM_linearSolverParams(A)->solver) { case NS_CS_LUSOL: info = !cs_lusol(1, NM_csc(A), b, DBL_EPSILON); break; #ifdef WITH_MUMPS case NS_MUMPS: { /* the mumps instance is initialized (call with job=-1) */ DMUMPS_STRUC_C* mumps_id = NM_MUMPS_id(A); mumps_id->rhs = b; mumps_id->job = 6; /* compute the solution */ dmumps_c(mumps_id); /* clean the mumps instance */ mumps_id->job = -2; dmumps_c(mumps_id); info = mumps_id->info[0]; if (info > 0) { if (verbose > 0) { printf("NM_gesv: MUMPS fails : info(1)=%d, info(2)=%d\n", info, mumps_id->info[1]); } } if (verbose > 1) { printf("MUMPS : condition number %g\n", mumps_id->rinfog[9]); printf("MUMPS : component wise scaled residual %g\n", mumps_id->rinfog[6]); printf("MUMPS : \n"); } /* Here we free mumps_id ... */ free(NM_linearSolverParams(A)->solver_data); NM_linearSolverParams(A)->solver_data = NULL; break; } #endif default: { fprintf(stderr, "NM_gesv: unknown sparse linearsolver : %d\n", NM_linearSolverParams(A)->solver); exit(EXIT_FAILURE); } } break; } default: assert (0 && "NM_gesv unknown storageType"); } /* some time we cannot find a solution to a linear system, and its fine, for * instance with the minFBLSA. Therefore, we should not check here for * problems, but the calling function has to check the return code.*/ // CHECK_RETURN(info); return info; }
ESymSolverStatus MumpsSolverInterface::Factorization( bool check_NegEVals, Index numberOfNegEVals) { DBG_START_METH("MumpsSolverInterface::Factorization", dbg_verbosity); DMUMPS_STRUC_C* mumps_data = (DMUMPS_STRUC_C*)mumps_ptr_; mumps_data->job = 2;//numerical factorization dump_matrix(mumps_data); Jnlst().Printf(J_MOREDETAILED, J_LINEAR_ALGEBRA, "Calling MUMPS-2 for numerical 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-2 for numerical factorization at cpu time %10.3f (wall %10.3f).\n", CpuTime(), WallclockTime()); int error = mumps_data->info[0]; //Check for errors if (error == -8 || error == -9) {//not enough memory const Index trycount_max = 20; for (int trycount=0; trycount<trycount_max; trycount++) { Jnlst().Printf(J_WARNING, J_LINEAR_ALGEBRA, "MUMPS returned INFO(1) = %d and requires more memory, reallocating. Attempt %d\n", error,trycount+1); Jnlst().Printf(J_WARNING, J_LINEAR_ALGEBRA, " Increasing icntl[13] from %d to ", mumps_data->icntl[13]); double mem_percent = mumps_data->icntl[13]; mumps_data->icntl[13] = (Index)(2.0 * mem_percent); Jnlst().Printf(J_WARNING, J_LINEAR_ALGEBRA, "%d.\n", mumps_data->icntl[13]); dump_matrix(mumps_data); Jnlst().Printf(J_MOREDETAILED, J_LINEAR_ALGEBRA, "Calling MUMPS-2 (repeated) for numerical 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-2 (repeated) for numerical factorization at cpu time %10.3f (wall %10.3f).\n", CpuTime(), WallclockTime()); error = mumps_data->info[0]; if (error != -8 && error != -9) break; } if (error == -8 || error == -9) { Jnlst().Printf(J_ERROR, J_LINEAR_ALGEBRA, "MUMPS was not able to obtain enough memory.\n"); return SYMSOLVER_FATAL_ERROR; } } Jnlst().Printf(J_DETAILED, J_LINEAR_ALGEBRA, "Number of doubles for MUMPS to hold factorization (INFO(9)) = %d\n", mumps_data->info[8]); Jnlst().Printf(J_DETAILED, J_LINEAR_ALGEBRA, "Number of integers for MUMPS to hold factorization (INFO(10)) = %d\n", mumps_data->info[9]); if (error == -10) {//system is singular Jnlst().Printf(J_DETAILED, J_LINEAR_ALGEBRA, "MUMPS returned INFO(1) = %d matrix is singular.\n",error); return SYMSOLVER_SINGULAR; } negevals_ = mumps_data->infog[11]; if (error == -13) { Jnlst().Printf(J_ERROR, J_LINEAR_ALGEBRA, "MUMPS returned INFO(1) =%d - out of memory when trying to allocate %d %s.\nIn some cases it helps to decrease the value of the option \"mumps_mem_percent\".\n", error, mumps_data->info[1] < 0 ? -mumps_data->info[1] : mumps_data->info[1], mumps_data->info[1] < 0 ? "MB" : "bytes"); return SYMSOLVER_FATAL_ERROR; } if (error < 0) {//some other error Jnlst().Printf(J_ERROR, J_LINEAR_ALGEBRA, "MUMPS returned INFO(1) =%d MUMPS failure.\n", error); return SYMSOLVER_FATAL_ERROR; } if (check_NegEVals && (numberOfNegEVals!=negevals_)) { Jnlst().Printf(J_DETAILED, J_LINEAR_ALGEBRA, "In MumpsSolverInterface::Factorization: negevals_ = %d, but numberOfNegEVals = %d\n", negevals_, numberOfNegEVals); return SYMSOLVER_WRONG_INERTIA; } 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; }
int MAIN__() { int argc=1; char * name = "c_example"; char ** argv ; #else int main(int argc, char ** argv) { #endif DMUMPS_STRUC_C id; int n = 6; int nz = 21; int irnL[] = {1,2,3,4,5,6,2,3,4,5,6,3,4,5,6,4,5,6,5,6,6}; int jcnL[] = {1,1,1,1,1,1,2,2,2,2,2,3,3,3,3,4,4,4,5,5,6}; int irnS[] = {1,2,3,2,3,3}; int jcnS[] = {1,1,1,2,2,3}; int *irn = irnL; int *jcn = jcnL; double a[21]; double rhs[6]; int myid, ierr, numP; #if defined(MAIN_COMP) argv = &name; #endif ierr = MPI_Init(&argc, &argv); ierr = MPI_Comm_rank(MPI_COMM_WORLD, &myid); ierr = MPI_Comm_size(MPI_COMM_WORLD, &numP); double nump = numP * 1.0; /* Define A and rhs */ rhs[0]=2.0;rhs[1]=2.0;rhs[2]=2.0;rhs[3]=2.0;rhs[4]=2.0;rhs[5]=2.0; a[0]=4169.95/nump; a[1]=0.0; a[2]=10075.0/nump; a[3]=-4030; a[4]=0.0; a[5]=0.0; a[6]=10084.0/nump; a[7]=-1612.0/nump; a[8]=0.0; a[9]=-8.9556; a[10]=-1612; a[11]=1354080.0/nump; a[12]=0.0; a[13]=1612.0; a[14]=193440.0; a[15]=4169.93; a[16]=0.0; a[17]=10075; a[18]=10084; a[19]=1612; a[20]=1354000; if (myid != 0) { nz = 6; a[0]=4169.95/nump; a[1]=0.0; a[2]=10075.0/nump; a[3]=10084.0/nump; a[4]=-1612.0/nump; a[5]=1354080.0/nump; irn = irnS; jcn = jcnS; } #define ICNTL(I) icntl[(I)-1] /* macro s.t. indices match documentation */ /* Initialize a MUMPS instance. Use MPI_COMM_WORLD */ id.job=JOB_INIT; id.par=1; id.sym=2; id.comm_fortran=USE_COMM_WORLD; /* parallel solver; distributed i/p matrix A */ id.ICNTL(5)=0; id.ICNTL(18)=3; dmumps_c(&id); /* Define the problem on the host */ /* id.n = n; id.nz =nz; id.irn=irn; id.jcn=jcn; id.a = a; id.rhs = rhs; */ /* parallel solver; distributed i/p matrix A */ id.ICNTL(5)=0; id.ICNTL(18)=3; id.n = n; id.nz_loc =nz; id.irn_loc=irn; id.jcn_loc=jcn; id.a_loc = a; id.rhs = rhs; /* No outputs */ id.ICNTL(1)=-1; id.ICNTL(2)=-1; id.ICNTL(3)=-1; id.ICNTL(4)=0; id.job=1; dmumps_c(&id); id.job=5; dmumps_c(&id); if (myid == 0) { printf("Solution is : (%8.6e %8.6e %8.6e %8.6e %8.6e %8.6e \n", rhs[0],rhs[1], rhs[2], rhs[3], rhs[4], rhs[5]); } rhs[0]=2.0;rhs[1]=2.0;rhs[2]=2.0;rhs[3]=1.0;rhs[4]=1.0;rhs[5]=1.0; id.job=3; dmumps_c(&id); /* Terminate instance */ id.job=JOB_END; dmumps_c(&id); if (myid == 0) { printf("Solution is : (%8.6e %8.6e %8.6e %8.6e %8.6e %8.6e \n", rhs[0],rhs[1], rhs[2], rhs[3], rhs[4], rhs[5]); } ierr = MPI_Finalize(); return 0; }
void operator() ( DMUMPS_STRUC_C& struc ) const { dmumps_c( &struc ) ; }
void mexFunction(int nlhs, mxArray *plhs[ ], int nrhs, const mxArray *prhs[ ]) { int i,j,pos; int *ptr_int; double *ptr_matlab; #if MUMPS_ARITH == MUMPS_ARITH_z double *ptri_matlab; #endif mwSize tmp_m,tmp_n; /* C pointer for input parameters */ size_t inst_address; mwSize n,m,ne, netrue ; int job; mwIndex *irn_in,*jcn_in; /* variable for multiple and sparse rhs */ int posrhs; mwSize nbrhs,ldrhs, nz_rhs; mwIndex *irhs_ptr, *irhs_sparse; double *rhs_sparse; #if MUMPS_ARITH == MUMPS_ARITH_z double *im_rhs_sparse; #endif DMUMPS_STRUC_C *dmumps_par; int dosolve = 0; int donullspace = 0; int doanalysis = 0; int dofactorize = 0; EXTRACT_FROM_MATLAB_TOVAL(JOB,job); doanalysis = (job == 1 || job == 4 || job == 6); dofactorize = (job == 2 || job == 4 || job == 5 || job == 6); dosolve = (job == 3 || job == 5 || job == 6); if(job == -1){ DMUMPS_alloc(&dmumps_par); EXTRACT_FROM_MATLAB_TOVAL(SYM,dmumps_par->sym); dmumps_par->job = -1; dmumps_par->par = 1; dmumps_c(dmumps_par); dmumps_par->nz = -1; dmumps_par->nz_alloc = -1; }else{ EXTRACT_FROM_MATLAB_TOVAL(INST,inst_address); ptr_int = (int *) inst_address; dmumps_par = (DMUMPS_STRUC_C *) ptr_int; if(job == -2){ dmumps_par->job = -2; dmumps_c(dmumps_par); /* If colsca/rowsca were freed by MUMPS, dmumps_par->colsca/rowsca are now null. Application of MYFREE in call below thus ok */ DMUMPS_free(&dmumps_par); }else{ /* check of input arguments */ n = mxGetN(A_IN); m = mxGetM(A_IN); if (!mxIsSparse(A_IN) || n != m ) mexErrMsgTxt("Input matrix must be a sparse square matrix"); jcn_in = mxGetJc(A_IN); ne = jcn_in[n]; irn_in = mxGetIr(A_IN); dmumps_par->n = (int)n; if(dmumps_par->n != n) mexErrMsgTxt("Input is too big; will not work...barfing out\n"); if(dmumps_par->sym != 0) netrue = (n+ne)/2; else netrue = ne; if(dmumps_par->nz_alloc < netrue || dmumps_par->nz_alloc >= 2*netrue){ MYFREE(dmumps_par->jcn); MYFREE(dmumps_par->irn); MYFREE(dmumps_par->a); MYMALLOC((dmumps_par->jcn),(int)netrue,int); MYMALLOC((dmumps_par->irn),(int)netrue,int); MYMALLOC((dmumps_par->a),(int)netrue,double2); dmumps_par->nz_alloc = (int)netrue; if (dmumps_par->nz_alloc != netrue) mexErrMsgTxt("Input is too big; will not work...barfing out\n"); } if(dmumps_par->sym == 0){ /* if analysis already performed then we only need to read numerical values Note that we suppose that matlab did not change the internal format of the matrix between the 2 calls */ if(doanalysis){ /* || dmumps_par->info[22] == 0 */ for(i=0;i<dmumps_par->n;i++){ for(j=jcn_in[i];j<jcn_in[i+1];j++){ (dmumps_par->jcn)[j] = i+1; (dmumps_par->irn)[j] = ((int)irn_in[j])+1; } } } dmumps_par->nz = (int)ne; if( dmumps_par->nz != ne) mexErrMsgTxt("Input is too big; will not work...barfing out\n"); #if MUMPS_ARITH == MUMPS_ARITH_z ptr_matlab = mxGetPr(A_IN); for(i=0;i<dmumps_par->nz;i++){ ((dmumps_par->a)[i]).r = ptr_matlab[i]; } ptr_matlab = mxGetPi(A_IN); if(ptr_matlab){ for(i=0;i<dmumps_par->nz;i++){ ((dmumps_par->a)[i]).i = ptr_matlab[i]; } }else{ for(i=0;i<dmumps_par->nz;i++){ ((dmumps_par->a)[i]).i = 0.0; } } #else ptr_matlab = mxGetPr(A_IN); for(i=0;i<dmumps_par->nz;i++){ (dmumps_par->a)[i] = ptr_matlab[i]; } #endif }else{ /* in the symmetric case we do not need to check doanalysis */ pos = 0; ptr_matlab = mxGetPr(A_IN); #if MUMPS_ARITH == MUMPS_ARITH_z ptri_matlab = mxGetPi(A_IN); #endif for(i=0;i<dmumps_par->n;i++){ for(j=jcn_in[i];j<jcn_in[i+1];j++){ if(irn_in[j] >= i){ if(pos >= netrue) mexErrMsgTxt("Input matrix must be symmetric"); (dmumps_par->jcn)[pos] = i+1; (dmumps_par->irn)[pos] = (int)irn_in[j]+1; #if MUMPS_ARITH == MUMPS_ARITH_z ((dmumps_par->a)[pos]).r = ptr_matlab[j]; if(ptri_matlab){ ((dmumps_par->a)[pos]).i = ptri_matlab[j]; }else{ ((dmumps_par->a)[pos]).i = 0.0; } #else (dmumps_par->a)[pos] = ptr_matlab[j]; #endif pos++; } } } dmumps_par->nz = pos; } EXTRACT_FROM_MATLAB_TOVAL(JOB,dmumps_par->job); EXTRACT_FROM_MATLAB_TOARR(ICNTL_IN,dmumps_par->icntl,int,40); EXTRACT_FROM_MATLAB_TOARR(CNTL_IN,dmumps_par->cntl,double,15); EXTRACT_FROM_MATLAB_TOPTR(PERM_IN,(dmumps_par->perm_in),int,((int)n)); /* colsca and rowsca are treated differently: it may happen that dmumps_par-> colsca is nonzero because it was set to a nonzero value on output (COLSCA_OUT) from MUMPS. Unfortunately if scaling was on output, one cannot currently provide scaling on input afterwards without reinitializing the instance */ EXTRACT_SCALING_FROM_MATLAB_TOPTR(COLSCA_IN,(dmumps_par->colsca),(dmumps_par->colsca_from_mumps),((int)n)); /* type always double */ EXTRACT_SCALING_FROM_MATLAB_TOPTR(ROWSCA_IN,(dmumps_par->rowsca),(dmumps_par->rowsca_from_mumps),((int)n)); /* type always double */ EXTRACT_FROM_MATLAB_TOARR(KEEP_IN,dmumps_par->keep,int,500); EXTRACT_FROM_MATLAB_TOARR(DKEEP_IN,dmumps_par->dkeep,double,230); dmumps_par->size_schur = (int)mxGetN(VAR_SCHUR); EXTRACT_FROM_MATLAB_TOPTR(VAR_SCHUR,(dmumps_par->listvar_schur),int,dmumps_par->size_schur); if(!dmumps_par->listvar_schur) dmumps_par->size_schur = 0; ptr_matlab = mxGetPr (RHS_IN); /* * To follow the "spirit" of the Matlab/Scilab interfaces, treat case of null * space separately. In that case, we initialize lrhs and nrhs, automatically * allocate the space needed, and do not rely on what is provided by the user * in component RHS, that is not touched. * * Note that, at the moment, the user should not call the solution step combined * with the factorization step when he/she sets icntl[25-1] to a non-zero value. * Hence we suppose in the following that infog[28-1] is available and that we * can use it. * * For users of scilab/matlab, it would still be nice to be able to set ICNTL(25)=-1, * and use JOB=6. If we want to make such a feature available, we should * call separately job=2 and job=3 even if job=5 or 6 and set nbrhs (and allocate * space correctly) between job=2 and job=3 calls to MUMPS. * */ if ( dmumps_par->icntl[25-1] == -1 && dmumps_par->infog[28-1] > 0 ) { dmumps_par->nrhs=dmumps_par->infog[28-1]; donullspace = dosolve; } else if ( dmumps_par->icntl[25-1] > 0 && dmumps_par->icntl[25-1] <= dmumps_par->infog[28-1] ) { dmumps_par->nrhs=1; donullspace = dosolve; } else { donullspace=0; } if (donullspace) { nbrhs=dmumps_par->nrhs; ldrhs=n; dmumps_par->lrhs=(int)n; MYMALLOC((dmumps_par->rhs),((dmumps_par->n)*(dmumps_par->nrhs)),double2); } else if((!dosolve) || ptr_matlab[0] == -9999 ) { /* rhs not already provided, or not used */ /* Case where dosolve is true and ptr_matlab[0]=-9999, this could cause problems: * 1/ RHS was not initialized while it should have been * 2/ RHS was explicitely initialized to -9999 but is not allocated of the right size */ EXTRACT_CMPLX_FROM_MATLAB_TOPTR(RHS_IN,(dmumps_par->rhs),double,1); }else{
//============================================================================= int Amesos_Mumps::SymbolicFactorization() { // erase data if present. if (IsSymbolicFactorizationOK_ && MDS.job != -777) Destroy(); IsSymbolicFactorizationOK_ = false; IsNumericFactorizationOK_ = false; CreateTimer(Comm()); CheckParameters(); AMESOS_CHK_ERR(ConvertToTriplet(false)); #if defined(HAVE_MPI) && defined(HAVE_AMESOS_MPI_C2F) if (MaxProcs_ != Comm().NumProc()) { if(MUMPSComm_) MPI_Comm_free(&MUMPSComm_); std::vector<int> ProcsInGroup(MaxProcs_); for (int i = 0 ; i < MaxProcs_ ; ++i) ProcsInGroup[i] = i; MPI_Group OrigGroup, MumpsGroup; MPI_Comm_group(MPI_COMM_WORLD, &OrigGroup); MPI_Group_incl(OrigGroup, MaxProcs_, &ProcsInGroup[0], &MumpsGroup); MPI_Comm_create(MPI_COMM_WORLD, MumpsGroup, &MUMPSComm_); #ifdef MUMPS_4_9 MDS.comm_fortran = (MUMPS_INT) MPI_Comm_c2f( MUMPSComm_); #else #ifndef HAVE_AMESOS_OLD_MUMPS MDS.comm_fortran = (DMUMPS_INT) MPI_Comm_c2f( MUMPSComm_); #else MDS.comm_fortran = (F_INT) MPI_Comm_c2f( MUMPSComm_); #endif #endif } else { const Epetra_MpiComm* MpiComm = dynamic_cast<const Epetra_MpiComm*>(&Comm()); assert (MpiComm != 0); #ifdef MUMPS_4_9 MDS.comm_fortran = (MUMPS_INT) MPI_Comm_c2f(MpiComm->GetMpiComm()); #else #ifndef HAVE_AMESOS_OLD_MUMPS MDS.comm_fortran = (DMUMPS_INT) MPI_Comm_c2f(MpiComm->GetMpiComm()); #else MDS.comm_fortran = (F_INT) MPI_Comm_c2f(MpiComm->GetMpiComm()); #endif #endif } #else // This next three lines of code were required to make Amesos_Mumps work // with Ifpack_SubdomainFilter. They is usefull in all cases // when using MUMPS on a subdomain. const Epetra_MpiComm* MpiComm = dynamic_cast<const Epetra_MpiComm*>(&Comm()); assert (MpiComm != 0); MDS.comm_fortran = (MUMPS_INT) MPI_Comm_c2f(MpiComm->GetMpiComm()); // only thing I can do, use MPI_COMM_WORLD. This will work in serial as well // Previously, the next line was uncommented, but we don't want MUMPS to work // on the global MPI comm, but on the comm associated with the matrix // MDS.comm_fortran = -987654; #endif MDS.job = -1 ; // Initialization MDS.par = 1 ; // Host IS involved in computations // MDS.sym = MatrixProperty_; MDS.sym = 0; // MatrixProperty_ is unititalized. Furthermore MUMPS // expects only half of the matrix to be provided for // symmetric matrices. Hence setting MDS.sym to be non-zero // indicating that the matrix is symmetric will only work // if we change ConvertToTriplet to pass only half of the // matrix. Bug #2331 and Bug #2332 - low priority RedistrMatrix(true); if (Comm().MyPID() < MaxProcs_) { dmumps_c(&(MDS)); // Initialize MUMPS static_cast<void>( CheckError( ) ); } MDS.n = Matrix().NumGlobalRows(); // fix pointers for nonzero pattern of A. Numerical values // will be entered in PerformNumericalFactorization() if (Comm().NumProc() != 1) { MDS.nz_loc = RedistrMatrix().NumMyNonzeros(); if (Comm().MyPID() < MaxProcs_) { MDS.irn_loc = &Row[0]; MDS.jcn_loc = &Col[0]; } } else { if (Comm().MyPID() == 0) { MDS.nz = Matrix().NumMyNonzeros(); MDS.irn = &Row[0]; MDS.jcn = &Col[0]; } } // scaling if provided by the user if (RowSca_ != 0) { MDS.rowsca = RowSca_; MDS.colsca = ColSca_; } // given ordering if provided by the user if (PermIn_ != 0) { MDS.perm_in = PermIn_; } MDS.job = 1; // Request symbolic factorization SetICNTLandCNTL(); // Perform symbolic factorization ResetTimer(); if (Comm().MyPID() < MaxProcs_) dmumps_c(&(MDS)); SymFactTime_ = AddTime("Total symbolic factorization time", SymFactTime_); int IntWrong = CheckError()?1:0 ; int AnyWrong; Comm().SumAll( &IntWrong, &AnyWrong, 1 ) ; bool Wrong = AnyWrong > 0 ; if ( Wrong ) { AMESOS_CHK_ERR( StructurallySingularMatrixError ) ; } IsSymbolicFactorizationOK_ = true ; NumSymbolicFact_++; return 0; }
/* Factorize - filling in rowsDropped and returning number dropped */ int ClpCholeskyMumps::factorize(const double * diagonal, int * rowsDropped) { const CoinBigIndex * columnStart = model_->clpMatrix()->getVectorStarts(); const int * columnLength = model_->clpMatrix()->getVectorLengths(); const int * row = model_->clpMatrix()->getIndices(); const double * element = model_->clpMatrix()->getElements(); const CoinBigIndex * rowStart = rowCopy_->getVectorStarts(); const int * rowLength = rowCopy_->getVectorLengths(); const int * column = rowCopy_->getIndices(); const double * elementByRow = rowCopy_->getElements(); int numberColumns = model_->clpMatrix()->getNumCols(); int iRow; double * work = new double[numberRows_]; CoinZeroN(work, numberRows_); const double * diagonalSlack = diagonal + numberColumns; int newDropped = 0; double largest; //double smallest; //perturbation double perturbation = model_->diagonalPerturbation() * model_->diagonalNorm(); perturbation = 0.0; perturbation = perturbation * perturbation; if (perturbation > 1.0) { #ifdef COIN_DEVELOP //if (model_->model()->logLevel()&4) std::cout << "large perturbation " << perturbation << std::endl; #endif perturbation = sqrt(perturbation);; perturbation = 1.0; } double delta2 = model_->delta(); // add delta*delta to diagonal delta2 *= delta2; for (iRow = 0; iRow < numberRows_; iRow++) { double * put = sparseFactor_ + choleskyStart_[iRow] - 1; // Fortran int * which = choleskyRow_ + choleskyStart_[iRow] - 1; // Fortran int number = choleskyStart_[iRow+1] - choleskyStart_[iRow]; if (!rowLength[iRow]) rowsDropped_[iRow] = 1; if (!rowsDropped_[iRow]) { CoinBigIndex startRow = rowStart[iRow]; CoinBigIndex endRow = rowStart[iRow] + rowLength[iRow]; work[iRow] = diagonalSlack[iRow] + delta2; for (CoinBigIndex k = startRow; k < endRow; k++) { int iColumn = column[k]; if (!whichDense_ || !whichDense_[iColumn]) { CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = columnStart[iColumn] + columnLength[iColumn]; double multiplier = diagonal[iColumn] * elementByRow[k]; for (CoinBigIndex j = start; j < end; j++) { int jRow = row[j]; if (jRow >= iRow && !rowsDropped_[jRow]) { double value = element[j] * multiplier; work[jRow] += value; } } } } int j; for (j = 0; j < number; j++) { int jRow = which[j] - 1; // to Fortran put[j] = work[jRow]; work[jRow] = 0.0; } } else { // dropped int j; for (j = 1; j < number; j++) { put[j] = 0.0; } put[0] = 1.0; } } //check sizes double largest2 = maximumAbsElement(sparseFactor_, sizeFactor_); largest2 *= 1.0e-20; largest = CoinMin(largest2, 1.0e-11); int numberDroppedBefore = 0; for (iRow = 0; iRow < numberRows_; iRow++) { int dropped = rowsDropped_[iRow]; // Move to int array rowsDropped[iRow] = dropped; if (!dropped) { CoinBigIndex start = choleskyStart_[iRow] - 1; // to Fortran double diagonal = sparseFactor_[start]; if (diagonal > largest2) { sparseFactor_[start] = CoinMax(diagonal, 1.0e-10); } else { sparseFactor_[start] = CoinMax(diagonal, 1.0e-10); rowsDropped[iRow] = 2; numberDroppedBefore++; } } } delete [] work; // code here mumps_->a_elt = sparseFactor_; mumps_->rhs = NULL; mumps_->job = 2; // factorize dmumps_c(mumps_); if (mumps_->infog[0]) { COIN_DETAIL_PRINT(printf("MUMPS factorization failed -error %d %d\n", mumps_->infog[0], mumps_->infog[1])); } choleskyCondition_ = 1.0; bool cleanCholesky; if (model_->numberIterations() < 2000) cleanCholesky = true; else cleanCholesky = false; if (cleanCholesky) { //drop fresh makes some formADAT easier //int oldDropped=numberRowsDropped_; if (newDropped || numberRowsDropped_) { //std::cout <<"Rank "<<numberRows_-newDropped<<" ( "<< // newDropped<<" dropped)"; //if (newDropped>oldDropped) //std::cout<<" ( "<<newDropped-oldDropped<<" dropped this time)"; //std::cout<<std::endl; newDropped = 0; for (int i = 0; i < numberRows_; i++) { int dropped = rowsDropped[i]; rowsDropped_[i] = (char)dropped; if (dropped == 2) { //dropped this time rowsDropped[newDropped++] = i; rowsDropped_[i] = 0; } } numberRowsDropped_ = newDropped; newDropped = -(2 + newDropped); } } else { if (newDropped) { newDropped = 0; for (int i = 0; i < numberRows_; i++) { int dropped = rowsDropped[i]; rowsDropped_[i] = (char)dropped; if (dropped == 2) { //dropped this time rowsDropped[newDropped++] = i; rowsDropped_[i] = 1; } } } numberRowsDropped_ += newDropped; if (numberRowsDropped_ && 0) { std::cout << "Rank " << numberRows_ - numberRowsDropped_ << " ( " << numberRowsDropped_ << " dropped)"; if (newDropped) { std::cout << " ( " << newDropped << " dropped this time)"; } std::cout << std::endl; } } status_ = 0; return newDropped; }
int Amesos_Mumps::Solve() { if (IsNumericFactorizationOK_ == false) AMESOS_CHK_ERR(NumericFactorization()); Epetra_MultiVector* vecX = Problem_->GetLHS(); Epetra_MultiVector* vecB = Problem_->GetRHS(); int NumVectors = vecX->NumVectors(); if ((vecX == 0) || (vecB == 0)) AMESOS_CHK_ERR(-1); if (NumVectors != vecB->NumVectors()) AMESOS_CHK_ERR(-1); if (Comm().NumProc() == 1) { // do not import any data for (int j = 0 ; j < NumVectors; j++) { ResetTimer(); MDS.job = 3; // Request solve for (int i = 0 ; i < Matrix().NumMyRows() ; ++i) (*vecX)[j][i] = (*vecB)[j][i]; MDS.rhs = (*vecX)[j]; dmumps_c(&(MDS)) ; // Perform solve static_cast<void>( CheckError( ) ); // Can hang SolveTime_ = AddTime("Total solve time", SolveTime_); } } else { Epetra_MultiVector SerialVector(SerialMap(),NumVectors); ResetTimer(); AMESOS_CHK_ERR(SerialVector.Import(*vecB,SerialImporter(),Insert)); VecRedistTime_ = AddTime("Total vector redistribution time", VecRedistTime_); for (int j = 0 ; j < NumVectors; j++) { if (Comm().MyPID() == 0) MDS.rhs = SerialVector[j]; // solve the linear system and take time MDS.job = 3; ResetTimer(); if (Comm().MyPID() < MaxProcs_) dmumps_c(&(MDS)) ; // Perform solve static_cast<void>( CheckError( ) ); // Can hang SolveTime_ = AddTime("Total solve time", SolveTime_); } // ship solution back and take timing ResetTimer(); AMESOS_CHK_ERR(vecX->Export(SerialVector,SerialImporter(),Insert)); VecRedistTime_ = AddTime("Total vector redistribution time", VecRedistTime_); } if (ComputeTrueResidual_) ComputeTrueResidual(Matrix(), *vecX, *vecB, UseTranspose(), "Amesos_Mumps"); if (ComputeVectorNorms_) ComputeVectorNorms(*vecX, *vecB, "Amesos_Mumps"); NumSolve_++; return(0) ; }