inverse.hpp concepts serif/utils/error/errors.hpp serif/solver/preconditioner/recipes/block.hpp serif/backend/mfem/solver/preconditioner/computations/physical_blocks.hpp serif/backend/mfem/solver/preconditioner/inverse/diagonal.hpp serif/backend/mfem/solver/preconditioner/inverse/dense.hpp serif/backend/mfem/solver/preconditioner/inverse/amg.hpp serif/backend/mfem/solver/preconditioner/inverse/sparse_direct.hpp serif/solver/preconditioner/strategies/inverse/diagonal.hpp src/include/serif/backend/mfem/solver/preconditioner/graph.hpp serif serif::solver serif::solver::preconditioner serif::solver::preconditioner::computations #pragmaonce #include<concepts> #include"serif/utils/error/errors.hpp" #include"serif/solver/preconditioner/recipes/block.hpp" #include"serif/backend/mfem/solver/preconditioner/computations/physical_blocks.hpp" #include"serif/backend/mfem/solver/preconditioner/inverse/diagonal.hpp" #include"serif/backend/mfem/solver/preconditioner/inverse/dense.hpp" #include"serif/backend/mfem/solver/preconditioner/inverse/amg.hpp" #include"serif/backend/mfem/solver/preconditioner/inverse/sparse_direct.hpp" #include"serif/solver/preconditioner/strategies/inverse/diagonal.hpp" namespaceserif::solver::preconditioner::computations { template<typenameStrategy> inlineconstexprboolneeds_diagonal=std::same_as<Strategy,strategies::inverse::Diagonal>; template<typenameStrategy> inlineconstexprboolneeds_matrix=std::same_as<Strategy,strategies::inverse::DenseDirect>||std::same_as<Strategy,strategies::inverse::FixedAMG>|| std::same_as<Strategy,strategies::inverse::SparseDirect>; template<typenameStrategy> [[nodiscard]]std::expected<backend::mfem::Inverse,Failure>invert_matrix(std::shared_ptr<const::mfem::SparseMatrix>matrix,constStrategy&strategy) { usingnamespacebackend::mfem; ifconstexpr(std::same_as<Strategy,strategies::inverse::DenseDirect>) { ::mfem::DenseMatrixdense; matrix->ToDenseMatrix(dense); returntry_dense_inverse(dense,strategy); } elseifconstexpr(std::same_as<Strategy,strategies::inverse::SparseDirect>) { returntry_sparse_direct_inverse(std::move(matrix),strategy); } else { returntry_amg_inverse(std::move(matrix),strategy); } } template<typenameRow,typenameField,typenameStrategy> [[nodiscard]]autoinverse(constBlockPreconditioner<Row,Field,Strategy>&choice) { usingnamespaceutils::dependencies; usingRecipe=BlockPreconditioner<Row,Field,Strategy>; usingRows=typenameRecipe::Rows; usingValues=typenameRecipe::Values; usingBlock=operators::backend::mfem::LinearizedBlock; usingResult=backend::mfem::Inverse; ifconstexpr(std::same_as<Strategy,strategies::inverse::Diagonal>) { returnmake_computation<typenameRecipe::Result,InputList<keys::Diagonal<Rows,Values>>>( [](conststd::vector<double>&diagonal) { returnbackend::mfem::try_diagonal_inverse(diagonal); }); } elseifconstexpr(std::same_as<Strategy,strategies::inverse::SparseDirect>) { //Thecomputationlivesaslongasthepreconditioner,soNewtonstepsshareonesymbolicanalysis. returnmake_computation<typenameRecipe::Result,InputList<keys::Matrix<Rows,Values>>>( [strategy=choice.inverse,cache=std::make_shared<backend::mfem::SparseDirectCache>()](conststd::shared_ptr<const::mfem::SparseMatrix>&matrix) { returnbackend::mfem::try_sparse_direct_inverse(matrix,strategy,cache.get()); }); } elseifconstexpr(needs_matrix<Strategy>) { returnmake_computation<typenameRecipe::Result,InputList<keys::Matrix<Rows,Values>>>( [strategy=choice.inverse](conststd::shared_ptr<const::mfem::SparseMatrix>&matrix) { returninvert_matrix(matrix,strategy); }); } else { returnmake_computation<typenameRecipe::Result,InputList<keys::Block<Rows,Values>>>( [strategy=choice.inverse](constBlock&block)->std::expected<Result,Failure> { usingnamespaceutils::errors; autoresult=strategy.try_inverse(block); if(!result) { returnresult; } if(!result->action) { returnstd::unexpected(Failure{SERiFErrorCode::PRECONDITIONER_INVALID_OPERATOR, format_error_message<SERiFErrorCode::PRECONDITIONER_INVALID_OPERATOR>("Acustominversereturnednoaction.Returnanownedinversefortheselectedphysicalblockorapreparationfailure.")}); } if(result->action->Height()!=block.action()->Width()||result->action->Width()!=block.action()->Height()) { returnstd::unexpected(Failure{SERiFErrorCode::PRECONDITIONER_SIZE_MISMATCH, format_error_message<SERiFErrorCode::PRECONDITIONER_SIZE_MISMATCH>("Acustominversemustreversethedimensionsofitsselectedphysicalblock.Returntheinverseinthatblock'sdeclaredequationandunknowncoordinates.")}); } if(result->contract!=ApplicationContract::fixed_linear&&result->contract!=ApplicationContract::variable) { returnstd::unexpected(Failure{SERiFErrorCode::PRECONDITIONER_INVALID_OPTIONS, format_error_message<SERiFErrorCode::PRECONDITIONER_INVALID_OPTIONS>("Acustominversemustdeclarefixed-linearorvariableapplication.Selectthecontractrequiredbyitsnumericalalgorithm.")}); } returnresult; }); } } }//namespaceserif::solver::preconditioner::computations