direct_lu_umfpack.cpp direct_lu.hpp algorithm vector umfpack.h serif::solver::preconditioner::backend::mfem::detail::DirectLUPattern::State serif::solver::preconditioner::backend::mfem::detail::DirectLU::State serif serif::solver serif::solver::preconditioner serif::solver::preconditioner::backend serif::solver::preconditioner::backend::mfem serif::solver::preconditioner::backend::mfem::detail //sparse_direct=umfpack:SuiteSparseUMFPACK,theportablebackend(Linux,macOS,Windows). #include"direct_lu.hpp" #include<algorithm> #include<vector> #include<umfpack.h> namespaceserif::solver::preconditioner::backend::mfem::detail { structDirectLUPattern::State { intsize{0}; std::vector<int>column_starts;//UMFPACK'sintinterface;MFEMindicesareint std::vector<int>row_indices; std::vector<double>control=std::vector<double>(UMFPACK_CONTROL); void*symbolic{nullptr}; }; structDirectLU::State { std::shared_ptr<constDirectLUPattern>pattern; std::vector<double>values; void*numeric{nullptr}; mutablestd::vector<double>right; mutablestd::vector<int>integer_workspace; mutablestd::vector<double>workspace; }; constchar*direct_lu_backend()noexcept{return"umfpack";} booldirect_lu_available()noexcept{returntrue;} std::shared_ptr<constDirectLUPattern>DirectLUPattern::analyze(constintsize,constlong*column_starts,constint*row_indices,constdouble*values,int&status) { autostate=std::make_unique<State>(); state->size=size; state->column_starts.assign(column_starts,column_starts+size+1); state->row_indices.assign(row_indices,row_indices+column_starts[size]); umfpack_di_defaults(state->control.data()); //Thepreconditionerneedsnoiterativerefinement;FGMREScorrectstheoutersolution. state->control[UMFPACK_IRSTEP]=0.0; //METIS:onthebenchmarkpotentialblockitleaves20%lessfillthanthedefaultordering(11.2Mvs14.0M //entries)andfactorsslightlyfaster.SuiteSparsebuildswithoutMETISrejectit,soretrywiththedefault. state->control[UMFPACK_ORDERING]=UMFPACK_ORDERING_METIS; std::vector<double>info(UMFPACK_INFO); status=umfpack_di_symbolic(size,size,state->column_starts.data(),state->row_indices.data(),values, &state->symbolic,state->control.data(),info.data()); if(status!=UMFPACK_OK){ umfpack_di_defaults(state->control.data()); state->control[UMFPACK_IRSTEP]=0.0; status=umfpack_di_symbolic(size,size,state->column_starts.data(),state->row_indices.data(),values, &state->symbolic,state->control.data(),info.data()); } if(status!=UMFPACK_OK){returnnullptr;} returnstd::shared_ptr<constDirectLUPattern>(newDirectLUPattern(std::move(state))); } DirectLUPattern::DirectLUPattern(std::unique_ptr<State>state):m_state(std::move(state)){} DirectLUPattern::~DirectLUPattern() { if(m_state&&m_state->symbolic){umfpack_di_free_symbolic(&m_state->symbolic);} } boolDirectLUPattern::matches(constintsize,constlong*column_starts,constint*row_indices)const { returnsize==m_state->size&&std::equal(m_state->column_starts.begin(),m_state->column_starts.end(),column_starts)&& std::equal(m_state->row_indices.begin(),m_state->row_indices.end(),row_indices); } std::unique_ptr<DirectLU>DirectLU::factor(std::shared_ptr<constDirectLUPattern>pattern,constdouble*values,int&status) { auto&shape=*pattern->m_state; autostate=std::make_unique<State>(); state->values.assign(values,values+shape.column_starts[static_cast<std::size_t>(shape.size)]); state->right.resize(static_cast<std::size_t>(shape.size)); state->integer_workspace.resize(static_cast<std::size_t>(shape.size)); state->workspace.resize(5*static_cast<std::size_t>(shape.size));//wsolvewithoutiterativerefinement std::vector<double>info(UMFPACK_INFO); //umfpack_di_numericreadsthesymbolicobjectwithoutmodifyingit. status=umfpack_di_numeric(shape.column_starts.data(),shape.row_indices.data(),state->values.data(),shape.symbolic, &state->numeric,shape.control.data(),info.data()); if(status!=UMFPACK_OK) { umfpack_di_free_numeric(&state->numeric); returnnullptr; } state->pattern=std::move(pattern); returnstd::unique_ptr<DirectLU>(newDirectLU(std::move(state))); } DirectLU::DirectLU(std::unique_ptr<State>state):m_state(std::move(state)){} DirectLU::~DirectLU() { if(m_state&&m_state->numeric){umfpack_di_free_numeric(&m_state->numeric);} } voidDirectLU::solve(constdouble*right,double*solution)const { constauto&shape=*m_state->pattern->m_state; std::copy(right,right+shape.size,m_state->right.begin()); std::vector<double>info(UMFPACK_INFO); umfpack_di_wsolve(UMFPACK_A,shape.column_starts.data(),shape.row_indices.data(),m_state->values.data(),solution, m_state->right.data(),m_state->numeric,shape.control.data(),info.data(),m_state->integer_workspace.data(), m_state->workspace.data()); } //UMFPACKhasnomultipleright-hand-sidesolve. voidDirectLU::solve_many(constintcount,constdouble*right,double*solution)const { conststd::size_tsize=static_cast<std::size_t>(m_state->pattern->m_state->size); std::vector<double>copy(right,right+size*static_cast<std::size_t>(count)); for(intcolumn=0;column<count;++column) { solve(copy.data()+size*static_cast<std::size_t>(column),solution+size*static_cast<std::size_t>(column)); } } }//namespaceserif::solver::preconditioner::backend::mfem::detail