graph.hpp tuple utility serif/backend/mfem/solver/preconditioner/computations/inverse.hpp serif/backend/mfem/solver/preconditioner/computations/coupling.hpp serif/backend/mfem/solver/preconditioner/computations/ordering.hpp serif/utils/dependencies/computation_graph.hpp src/include/serif/backend/mfem/model/preconditioning/computations.hpp src/include/serif/solver/preconditioner/preconditioner.hpp serif serif::solver serif::solver::preconditioner serif::solver::preconditioner::detail #pragmaonce #include<tuple> #include<utility> #include"serif/backend/mfem/solver/preconditioner/computations/inverse.hpp" #include"serif/backend/mfem/solver/preconditioner/computations/coupling.hpp" #include"serif/backend/mfem/solver/preconditioner/computations/ordering.hpp" #include"serif/utils/dependencies/computation_graph.hpp" namespaceserif::solver::preconditioner { namespacedetail { template<typenameRow,typenameField,typenameStrategy> [[nodiscard]]autopreconditioner_computations(constBlockPreconditioner<Row, Field, Strategy>&choice); template<typenameFirst,typenameSecond,typenamePolicy> [[nodiscard]]autopreconditioner_computations(constCoupledPreconditioner<First, Second, Policy>&choice); template<typenameFields,typenameConstraints> [[nodiscard]]autopreconditioner_computations(constBorderedPreconditioner<Fields, Constraints>&choice); template<typenameRow,typenameField,typenameStrategy> [[nodiscard]]autopreconditioner_computations(constBlockPreconditioner<Row, Field, Strategy>&choice) { usingRecipe=BlockPreconditioner<Row, Field, Strategy>; ifconstexpr(computations::needs_diagonal<Strategy>) { returnstd::tuple{computations::physical_diagonal<typename Recipe::Rows, typename Recipe::Values>(),computations::inverse(choice)}; } elseifconstexpr(computations::needs_matrix<Strategy>) { returnstd::tuple{computations::physical_matrix<typename Recipe::Rows, typename Recipe::Values>(),computations::inverse(choice)}; } else { returnstd::tuple{computations::inverse(choice)}; } } template<typenameFirst,typenameSecond,typenamePolicy> [[nodiscard]]autopreconditioner_computations(constCoupledPreconditioner<First, Second, Policy>&choice) { returnstd::tuple_cat(preconditioner_computations(choice.first),preconditioner_computations(choice.second),std::tuple{computations::coupling(choice)}); } template<typenameFields,typenameConstraints> [[nodiscard]]autopreconditioner_computations(constBorderedPreconditioner<Fields, Constraints>&choice) { returnstd::tuple_cat(preconditioner_computations(choice.fields),std::tuple{computations::border(choice)}); } }//namespacedetail template<typenameRecipe> [[nodiscard]]automake_preconditioner_computations(constRecipe&choice) { returndetail::preconditioner_computations(choice); } template<typenameRecipe> [[nodiscard]]automake_preconditioner_graph(constRecipe&choice) { returnstd::apply([](auto...nodes) { returnutils::dependencies::make_computation_graph(std::move(nodes)...); },make_preconditioner_computations(choice)); } template<typenameRecipe,discretization::blocks::SystemLayoutTypeLayout,utils::dependencies::IsComputation...Additional> [[nodiscard]]automake_preconditioner_computations(constRecipe&choice,constLayout&,Additional...additional){ returnstd::apply([](auto...nodes){ usingGraph=decltype(utils::dependencies::make_computation_graph(std::move(nodes)...)); usingPhysicalKeys=typenamecomputations::detail::PhysicalSources<typenameGraph::Inputs>::Type; returnstd::tuple{std::move(nodes)...,computations::ordering<Recipe, Layout>(PhysicalKeys{})}; },std::tuple_cat(std::tuple{std::move(additional)...},make_preconditioner_computations(choice))); } template<typenameRecipe,discretization::blocks::SystemLayoutTypeLayout,utils::dependencies::IsComputation...Additional> [[nodiscard]]automake_preconditioner_graph(constRecipe&choice,constLayout&layout,Additional...additional){ returnstd::apply([](auto...nodes){ returnutils::dependencies::make_computation_graph(std::move(nodes)...); },make_preconditioner_computations(choice,layout,std::move(additional)...)); } }//namespaceserif::solver::preconditioner