volume_computations.hpp expected memory tuple utility serif/backend/mfem/operators/volume_stages.hpp serif/backend/mfem/operators/volume_inputs.hpp serif/utils/dependencies/dependencies.hpp src/compile_time_checks/serif/operators/computation_owners.cpp src/include/serif/backend/mfem/model/computations/interior.hpp src/include/serif/backend/mfem/model/computations/scalar_row.hpp serif serif::operators serif::operators::backend serif::operators::backend::mfem #pragmaonce #include<expected> #include<memory> #include<tuple> #include<utility> #include"serif/backend/mfem/operators/volume_stages.hpp" #include"serif/backend/mfem/operators/volume_inputs.hpp" #include"serif/utils/dependencies/dependencies.hpp" namespaceserif::operators::backend::mfem { template<std::size_tContribution,typenameOperandT,typenameScope=void> usingVolumeOperandResult= std::conditional_t<OperandEvaluator<OperandT>::geometry_dependent,typenamevolume_keys::Scoped<Scope>::templatePhysicalValues<Contribution,OperandT>, typenamevolume_keys::Scoped<Scope>::templateReferenceValues<Contribution,OperandT>>; template<std::size_tContribution,typenameOperandT,VolumeEquationEquationT,typenameSchemaT,typenameScope=void> [[nodiscard]]automake_operand_computations(conststd::shared_ptr<VolumeScratch>&scratch) { usingnamespaceutils::dependencies; usingBasis=ElementBatch<ElementBasis<EquationPlan<EquationT>::operand_count>>; usingGeometry=ElementBatch<ElementGeometry<EquationPlan<EquationT>::operand_count>>; usingBinding=discretization::backend::mfem::TermBinding<typenameOperandT::term_type,SchemaT>; usingReferenceValues=typenamevolume_keys::Scoped<Scope>::templateReferenceValues<Contribution,OperandT>; constautosample_values=make_computation<ReferenceValues,InputList<typenamevolume_keys::Scoped<Scope>::templateBasis<Contribution>,typenameOperandT::term_type>>( [scratch](constBasis&basis,constCoefficientView<Binding>&input) { returnsample_contribution_operand<EquationT, OperandT>(basis,input,scratch->workspace); }); ifconstexpr(OperandEvaluator<OperandT>::geometry_dependent) { constautomap_values=make_computation<typenamevolume_keys::Scoped<Scope>::templatePhysicalValues<Contribution,OperandT>, InputList<ReferenceValues,typenamevolume_keys::Scoped<Scope>::templateGeometry<Contribution>>>( [scratch](constOperandSamples&samples,constGeometry&geometry) { returnmap_contribution_operand<OperandT>(samples,geometry,scratch->workspace); }); returnstd::tuple{sample_values,map_values}; } else { returnstd::tuple{sample_values}; } } template<std::size_tIndex,typenameScope,VolumeEquationEquationT,typenameSchemaT,typenameContributionT,typename...Operands> [[nodiscard]]automake_contribution_computations(conststd::shared_ptr<constVolumeConfiguration<EquationT, SchemaT>>&configuration, conststd::shared_ptr<VolumeScratch>&scratch,ContributionBinding<ContributionT>contribution, utils::types::TypeList<Operands...>) { usingnamespaceutils::dependencies; usingPlan=EquationPlan<EquationT>; usingBasis=ElementBatch<ElementBasis<Plan::operand_count>>; usingGeometry=ElementBatch<ElementGeometry<Plan::operand_count>>; usingDisplacementBinding=typenameVolumeConfiguration<EquationT, SchemaT>::DisplacementBinding; constautoreference_basis=make_computation<typenamevolume_keys::Scoped<Scope>::templateBasis<Index>,InputList<typenamevolume_keys::Scoped<Scope>::Bindings>>( [configuration,scratch,contribution](constBasisBindings<Plan::column_count>&bindings) { returnsample_contribution_basis(*configuration,contribution,bindings,scratch->basis); }); constautogeometry=make_computation<typenamevolume_keys::Scoped<Scope>::templateGeometry<Index>, InputList<typenamevolume_keys::Scoped<Scope>::templateBasis<Index>,DisplacementCoefficients,CompactificationCoefficients>>( [configuration,scratch](constBasis&basis,constCoefficientView<DisplacementBinding>&displacement,constMappingCoefficients&compactification) { returnmap_contribution_geometry<EquationT, SchemaT, ContributionT>(*configuration,basis,displacement,compactification,scratch->workspace); }); constautooperand_values=std::tuple_cat(make_operand_computations<Index, Operands, EquationT, SchemaT, Scope>(scratch)...); constautoequation_values=make_computation<typenamevolume_keys::Scoped<Scope>::templateQuadratureLinearization<Index>, InputList<typenamevolume_keys::Scoped<Scope>::templateBasis<Index>, typenamevolume_keys::Scoped<Scope>::templateGeometry<Index>,VolumeOperandResult<Index, Operands, Scope>...>>( [scratch,contribution](constBasis&basis,constGeometry&geometry,constSamplesFor<Operands>&...samples) { returnevaluate_contribution_equation<EquationT,ContributionT,Operands...>(contribution,basis,geometry,scratch->workspace,samples...); }); constautogeometry_derivatives=make_computation<typenamevolume_keys::Scoped<Scope>::templateGeometryDerivatives<Index>, InputList<typenamevolume_keys::Scoped<Scope>::templateQuadratureLinearization<Index>>>( [configuration,scratch](constContributionData<Plan::operand_count>&data){ returndifferentiate_contribution_geometry<EquationT, SchemaT, ContributionT>(*configuration,data,scratch->workspace); }); returnstd::tuple_cat(std::tuple{reference_basis,geometry},operand_values,std::tuple{equation_values,geometry_derivatives}); } template<typenameScope=void,VolumeEquationEquationT,typenameSchemaT,std::size_t...Indices> [[nodiscard]]autoconnect_volume_contributions(conststd::shared_ptr<constVolumeConfiguration<EquationT, SchemaT>>&configuration,std::index_sequence<Indices...>) { usingnamespaceutils::dependencies; usingPlan=EquationPlan<EquationT>; constautoscratch=std::make_shared<VolumeScratch>(); constautocontributions=bind_contributions(configuration->equation); constautocalculations=std::tuple_cat(make_contribution_computations<Indices, Scope>( configuration,scratch,std::get<Indices>(contributions),typenamestd::tuple_element_t<Indices,equations::ContributionsOf<EquationT>>::Operands{})...); constautovolume= make_computation<typenamevolume_keys::Scoped<Scope>::Linearization, InputList<typenamevolume_keys::Scoped<Scope>::Bindings,typenamevolume_keys::Scoped<Scope>::templateQuadratureLinearization<Indices>..., typenamevolume_keys::Scoped<Scope>::templateGeometryDerivatives<Indices>...>>( [configuration,scratch](constBasisBindings<Plan::column_count>&bindings,constauto&...results) { //Thefirstgroupcontainsthephysicalequations;thesecondtheirlocalgeometryderivatives. constautovalues=std::tie(results...); autovolume=collect_volume_results(configuration,bindings,scratch->workspace,std::get<Indices>(values)...); if(volume){ volume->geometry_derivatives={std::get<sizeof...(Indices)+Indices>(values)...}; } returnvolume; }); returnstd::tuple_cat(calculations,std::tuple{volume}); } template<VolumeEquationEquationT,std::size_tIndex,typenameScope=void,typenameCacheT> voidreport_contribution_preparation(constCacheT&cache,NumericalWork&report) { usingPlan=EquationPlan<EquationT>; usingContribution=std::tuple_element_t<Index,equations::ContributionsOf<EquationT>>; constauto&basis=cache.templateget<typenamevolume_keys::Scoped<Scope>::templateBasis<Index>>(); constauto&status=cache.report(); std::size_tpoints=0; for(constauto&element:basis) { points+=element->rule->GetNPoints(); } if(status.templatestatus<typenamevolume_keys::Scoped<Scope>::templateGeometry<Index>>()==utils::dependencies::PreparationStatus::computed) { report.geometry_points+=points; } if(status.templatestatus<typenamevolume_keys::Scoped<Scope>::templateQuadratureLinearization<Index>>()==utils::dependencies::PreparationStatus::computed) { report.physics_points+=points; } else { report.reused_elements+=basis.size(); } Plan::templatefor_each_input<Contribution>( [&]<typenameOperandT>(OperandT,std::size_t) { if(status.templatestatus<typenamevolume_keys::Scoped<Scope>::templateReferenceValues<Index,OperandT>>()==utils::dependencies::PreparationStatus::computed) { report.sampled_operands+=basis.size(); } }); } template<typenameScope=void,VolumeEquationEquationT,typenameSchemaT> [[nodiscard]]automake_volume_equation_computations(std::shared_ptr<constEquationT>equation,constVolumeDiscretization<typename EquationT::Test, SchemaT>&discretization, VolumeOptionsoptions={}) { utils::errors::serif_ensure<utils::errors::SERiFErrorCode::INVALID_ARGUMENT>(equation!=nullptr,"Volumecomputationsrequireanowningequation;supplyanon-nullequationorretainedmodelmember."); validate_volume_discretization(discretization); constautoconfiguration=std::make_shared<constVolumeConfiguration<EquationT,SchemaT>>( VolumeConfiguration<EquationT, SchemaT>{.equation=std::move(equation),.discretization=discretization,.options=std::move(options)}); returnconnect_volume_contributions<Scope>(configuration,std::make_index_sequence<std::tuple_size_v<equations::ContributionsOf<EquationT>>>{}); } template<typenameScope=void,VolumeEquationEquationT,typenameSchemaT> [[nodiscard]]automake_volume_equation_computations(EquationTequation,constVolumeDiscretization<typename EquationT::Test, SchemaT>&discretization,VolumeOptionsoptions={}) { returnmake_volume_equation_computations<Scope>(std::make_shared<constEquationT>(std::move(equation)),discretization,std::move(options)); } template<typenameScope=void,VolumeEquationEquationT,typenameSchemaT,typenameInputsT> [[nodiscard]]automake_volume_equation_cache(EquationTequation,constVolumeDiscretization<typename EquationT::Test, SchemaT>&discretization,constInputsT&inputs, VolumeOptionsoptions={}) { returnstd::apply( [&](auto...calculations) { returnutils::dependencies::make_computation_cache<PreparationRejection>(inputs,std::move(calculations)...); }, make_volume_equation_computations<Scope>(std::move(equation),discretization,std::move(options))); } template<typenameCacheT,typenameScope=void> usingVolumeEquationOf=typenamestd::remove_cvref_t<decltype(std::declval<constCacheT&>().templateget<typenamevolume_keys::Scoped<Scope>::Linearization>())>::Equation; template<typenameScope=void,typenameCacheT,typenameDiscretizationT,typenameCoefficientsT> [[nodiscard]]std::expected<void,PreparationRejection>try_prepare_volume(CacheT&cache,constDiscretizationT&discretization,constCoefficientsT&term_coefficients, const::mfem::Vector&displacement_coefficients, PreparationModemode=PreparationMode::reuse_unchanged) { returntry_prepare_validated(cache, [&]() { constautoinputs= make_volume_inputs<VolumeEquationOf<CacheT, Scope>,Scope>(discretization,term_coefficients,displacement_coefficients); returncache.try_prepare(inputs,{},mode); }); } template<typenameScope=void,typenameCacheT,typenameDiscretizationT,typenameCoefficientsT> voidprepare_volume(CacheT&cache,constDiscretizationT&discretization,constCoefficientsT&term_coefficients,const::mfem::Vector&displacement_coefficients, PreparationModemode=PreparationMode::reuse_unchanged) { usingnamespaceutils::errors; constautoresult=try_prepare_volume<Scope>(cache,discretization,term_coefficients,displacement_coefficients,mode); if(!result) { serif_error<std::domain_error,SERiFErrorCode::INVALID_ARGUMENT>("{}preparationrejectedatelement{},point{}:{}",VolumeEquationOf<CacheT, Scope>::name, result.error().element,result.error().quadrature_point,result.error().message); } } template<typenameScope=void,typenameCacheT> [[nodiscard]]NumericalWorkvolume_work_report(constCacheT&cache) { usingEquation=VolumeEquationOf<CacheT, Scope>; NumericalWorkreport; if(cache.templatecontains<typenamevolume_keys::Scoped<Scope>::Linearization>()) { [&]<std::size_t...Indices>(std::index_sequence<Indices...>) { (report_contribution_preparation<Equation, Indices, Scope>(cache,report),...); }(std::make_index_sequence<std::tuple_size_v<equations::ContributionsOf<Equation>>>{}); } returnreport; } }//namespaceserif::operators::backend::mfem