linearized_block.cpp serif/backend/mfem/operators/linearized_block.hpp algorithm utility serif/utils/error/errors.hpp serif::operators::backend::mfem::LinearizedBlock::Data serif serif::operators serif::operators::backend serif::operators::backend::mfem #include"serif/backend/mfem/operators/linearized_block.hpp" #include<algorithm> #include<utility> #include"serif/utils/error/errors.hpp" namespaceserif::operators::backend::mfem { structLinearizedBlock::Datafinal { Actionaction; Diagonaldiagonal; Assemblyassembly; }; LinearizedBlock::LinearizedBlock(Actionaction,Diagonaldiagonal,Assemblyassembly) { utils::errors::serif_ensure<utils::errors::SERiFErrorCode::INVALID_ARGUMENT>(action!=nullptr, "Anacceptedphysicalblockrequiresanon-nulloperator.Supplytheactionfromasuccessfullinearization."); m_data=std::make_shared<constData>(Data{std::move(action),std::move(diagonal),std::move(assembly)}); } constLinearizedBlock::Action&LinearizedBlock::action()constnoexcept { returnm_data->action; } boolLinearizedBlock::has_diagonal()constnoexcept { returnstatic_cast<bool>(m_data->diagonal); } boolLinearizedBlock::has_assembly()constnoexcept { returnstatic_cast<bool>(m_data->assembly); } std::vector<double>LinearizedBlock::diagonal()const { utils::errors::serif_ensure<utils::errors::SERiFErrorCode::INVALID_ARGUMENT>(has_diagonal(), "Thisphysicalblockhasnodiagonalextractor.Supplyanelement-basedextractororanassembledmatrix."); returnm_data->diagonal(); } std::shared_ptr<const::mfem::SparseMatrix>LinearizedBlock::assemble()const { utils::errors::serif_ensure<utils::errors::SERiFErrorCode::INVALID_ARGUMENT>(has_assembly(), "Thisphysicalblockhasnosparseassembler.Supplyitsselectedmatrixassemblyroutine."); returnm_data->assembly(); } std::vector<double>checked_diagonal(constLinearizedBlock&block) { std::vector<double>result=block.diagonal(); utils::errors::serif_ensure<utils::errors::SERiFErrorCode::MATRIX_SHAPE_ERROR>(result.size()==static_cast<std::size_t>(std::min(block.action()->Height(),block.action()->Width())), "Aphysicalblockdiagonalmustcontainonevalueperdiagonalcoordinate.Returnthediagonalofthedeclaredoperatordimensions."); returnresult; } std::shared_ptr<const::mfem::SparseMatrix>checked_assembly(constLinearizedBlock&block) { constautoresult=block.assemble(); utils::errors::serif_ensure<utils::errors::SERiFErrorCode::MATRIX_SHAPE_ERROR>(result&&result->Finalized()&&result->Height()==block.action()->Height()&&result->Width()==block.action()->Width(), "Aphysicalblockassemblermustreturnanon-nullfinalizedmatrixmatchingitsdeclaredoperatordimensions."); returnresult; } LinearizedBlocklinearized_block(std::shared_ptr<const::mfem::SparseMatrix>matrix) { utils::errors::serif_ensure<utils::errors::SERiFErrorCode::INVALID_ARGUMENT>(matrix!=nullptr&&matrix->Finalized(), "Anassembledphysicalblockrequiresanon-nullfinalizedsparsematrix."); returnLinearizedBlock(matrix,[matrix]() { ::mfem::Vectordiagonal; matrix->GetDiag(diagonal); returnstd::vector<double>(diagonal.GetData(),diagonal.GetData()+diagonal.Size()); },[matrix]() { returnmatrix; }); } LinearizedBlocklinearized_block(std::shared_ptr<const::mfem::DenseMatrix>matrix) { utils::errors::serif_ensure<utils::errors::SERiFErrorCode::INVALID_ARGUMENT>(matrix!=nullptr, "Anassembledphysicalblockrequiresanon-nulldensematrix."); returnLinearizedBlock(matrix,[matrix]() { std::vector<double>diagonal(std::min(matrix->Height(),matrix->Width())); for(std::size_tindex=0;index<diagonal.size();++index) { diagonal[index]=(*matrix)(index,index); } returndiagonal; },[matrix]() { autosparse=std::make_shared<::mfem::SparseMatrix>(matrix->Height(),matrix->Width()); for(introw=0;row<matrix->Height();++row) { for(intcolumn=0;column<matrix->Width();++column) { sparse->Add(row,column,(*matrix)(row,column)); } } sparse->Finalize(); returnsparse; }); } }//namespaceserif::operators::backend::mfem