graph.hpp tuple utility serif/solver/preconditioner/computations/inverse.hpp serif/solver/preconditioner/computations/coupling.hpp serif/solver/preconditioner/computations/gravity.hpp serif/solver/preconditioner/computations/surface.hpp serif/solver/preconditioner/computations/ordering.hpp serif/solver/preconditioner/computations/coarse.hpp serif/utils/dependencies/computation_graph.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/solver/preconditioner/computations/inverse.hpp" #include"serif/solver/preconditioner/computations/coupling.hpp" #include"serif/solver/preconditioner/computations/gravity.hpp" #include"serif/solver/preconditioner/computations/surface.hpp" #include"serif/solver/preconditioner/computations/ordering.hpp" #include"serif/solver/preconditioner/computations/coarse.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<typenameGradient,typenamePotential,typenameMass,typenameSchur,typenamePolicy> [[nodiscard]]autopreconditioner_computations(constGravityPreconditioner<Gradient, Potential, Mass, Schur, Policy>&choice); template<typenameField,typenameRow,typenameStrategy,typenameBackend> [[nodiscard]]autopreconditioner_computations(constSurfacePreconditioner<Field, Row, Strategy, Backend>&choice); template<typenameRecipe> inlineconstexprboolcalibrated_surface=false; template<typenameField,typenameRow,typenameStrategy,typenameBackend> inlineconstexprboolcalibrated_surface<SurfacePreconditioner<Field, Row, Strategy, Backend>>=!std::same_as<Strategy,strategies::surface::ReferenceSurfaceMass>; template<typenameField,typenameRow,typenameStrategy,typenameBackend> [[nodiscard]]autosurface_inverse_computations(constSurfacePreconditioner<Field, Row, Strategy, Backend>&choice) { ifconstexpr(std::same_as<Strategy,strategies::surface::FittedSurfaceH1>) { returnstd::tuple{computations::surface_h1_fit(choice),computations::surface_positive_inverse(choice),computations::surface_inverse(choice)}; } else { returnstd::tuple{computations::surface_mass(choice),computations::surface_inverse(choice)}; } } template<typenameField,typenameRow,typenameStrategy,typenameBackend> [[nodiscard]]autopreconditioner_computations(constSurfacePreconditioner<Field, Row, Strategy, Backend>&choice) { ifconstexpr(std::same_as<Strategy,strategies::surface::ReferenceSurfaceMass>) { returnsurface_inverse_computations(choice); } else { returnstd::tuple_cat(std::tuple{computations::surface_target(choice)},surface_inverse_computations(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) { ifconstexpr(calibrated_surface<Second>) { returnstd::tuple_cat(preconditioner_computations(choice.first),std::tuple{computations::surface_target(choice.second,choice.first)}, surface_inverse_computations(choice.second),std::tuple{computations::coupling(choice)}); } elseifconstexpr(calibrated_surface<First>) { returnstd::tuple_cat(preconditioner_computations(choice.second),std::tuple{computations::surface_target(choice.first,choice.second)}, surface_inverse_computations(choice.first),std::tuple{computations::coupling(choice)}); } else { 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)}); } template<typenameGradient,typenamePotential,typenameMass,typenameSchur,typenamePolicy> [[nodiscard]]autopreconditioner_computations(constGravityPreconditioner<Gradient, Potential, Mass, Schur, Policy>&choice) { usingnamespaceutils::dependencies; constautomass=make_preconditioner<Gradient>(choice.mass_inverse); constautoextra_mass_diagonal=[]() { ifconstexpr(computations::needs_diagonal<Mass>) { returnstd::tuple{}; } else { returnstd::tuple{computations::physical_diagonal<KeyList<Gradient>,KeyList<Gradient>>()}; } }(); returnstd::tuple_cat(preconditioner_computations(mass),extra_mass_diagonal,std::tuple{computations::physical_matrix<KeyList<Potential>,KeyList<Gradient>>(),computations::gravity_schur<Gradient, Potential>(),computations::gravity_potential_inverse<Gradient, Potential>(choice.potential_inverse),computations::gravity(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_graph(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; returnutils::dependencies::make_computation_graph(std::move(nodes)...,computations::ordering<Recipe, Layout>(PhysicalKeys{})); },std::tuple_cat(std::tuple{std::move(additional)...},make_preconditioner_computations(choice))); } template<utils::dependencies::IsKeyListCoarseRows,utils::dependencies::IsKeyListCoarseValues,typenameRecipe,discretization::blocks::SystemLayoutTypeLayout> [[nodiscard]]automake_coarse_preconditioner_graph(constRecipe&unbordered,constLayout&,conststrategies::inverse::DenseDirect&options={.minimum_reciprocal_condition=1.0e-14}) { usingGraph=decltype(make_preconditioner_graph(unbordered)); usingPhysicalKeys=typenamecomputations::detail::PhysicalSources<typename Graph::Inputs>::Type; returnstd::apply([](auto...nodes) { returnutils::dependencies::make_computation_graph(std::move(nodes)...); },std::tuple_cat(make_preconditioner_computations(unbordered),std::tuple{computations::ordering<Recipe, Layout>(PhysicalKeys{}),computations::coarse_correction<CoarseRows, CoarseValues, Layout>(options)})); } }//namespaceserif::solver::preconditioner