boundary_rows.hpp serif/utils/error/nonfinite.hpp cmath vector serif/backend/mfem/geometry/surface/boundary_data.hpp serif/geometry/surface/linearization.hpp serif/backend/mfem/shared/finite.hpp src/include/serif/backend/mfem/geometry/surface/pressure_boundary.hpp src/include/serif/backend/mfem/geometry/surface/pressure_field_block.hpp serif serif::geometry serif::geometry::surface serif::geometry::surface::backend serif::geometry::surface::backend::mfem serif::geometry::surface::backend::mfem::detail #pragmaonce #include"serif/utils/error/nonfinite.hpp" #include<cmath> #include<vector> #include"serif/backend/mfem/geometry/surface/boundary_data.hpp" #include"serif/geometry/surface/linearization.hpp" #include"serif/backend/mfem/shared/finite.hpp" namespaceserif::geometry::surface::backend::mfem { namespacedetail { template<typenameBoundary> voidvalidate_boundary_output(constBoundary&boundary,const::mfem::Vector&result) { usingnamespaceutils::errors; boundary.validate(); serif_ensure<SERiFErrorCode::INVALID_DOF_COUNT, std::invalid_argument>(result.Size()==boundary.selected_rows->binding().size(),"Pressure-boundaryoutputmustmatchtheresidualbindingsize."); } template<typenameBoundary,typenameLinearizations> voidvalidate_boundary_samples(constBoundary&boundary,constLinearizations&linearizations) { usingnamespaceutils::errors; serif_ensure<SERiFErrorCode::INVALID_DOF_COUNT, std::invalid_argument>(linearizations.size()==static_cast<std::size_t>(boundary.selected_rows->size()),"Pressure-boundarylinearizationsmustmatchthecompiledrowselection."); } template<typenameBoundary> voidreplace_boundary_rows(constBoundary&boundary,const::mfem::Vector&values,::mfem::Vector&result) { usingnamespaceutils::errors; serif_ensure<SERiFErrorCode::NON_FINITE_VALUE_ERROR, NonFiniteValue>(utils::checks::is_finite(values),"Thepressure-boundaryactionproducedanon-finitevalue;rejectthiscandidate."); constauto&rows=boundary.selected_rows->reduced_dofs(); for(intindex=0;index<rows.Size();++index) { result[rows[index]]=values[index]; } } template<typenameBoundary,typenameLinearizations,typenameDirections,typename...Terms> [[nodiscard]]::mfem::Vectorboundary_jacobian_action(constBoundary&boundary,constLinearizations&linearizations,constDirections&directions,utils::dependencies::KeyList<Terms...>) { usingnamespaceutils::errors; ::mfem::Vectorresult(boundary.selected_rows->size()); ::mfem::Vectorsamples(result.Size()); result=0.0; constautoadd_direction=[&]<typenameTerm>() { constauto&trace=boundary.traces.templateget<Term>(); constauto&direction=directions.templateget<Term>(); serif_ensure<SERiFErrorCode::CACHE_FE_BINDING_ERROR, std::invalid_argument>(&direction.binding==&trace.binding(),"Apressure-boundarydirectionmustusethebindingthatcompileditstrace."); trace.binding().validate_values(direction.values); trace.interpolation().Mult(direction.values,samples); for(intindex=0;index<result.Size();++index) { result[index]+=linearizations[index].field_derivatives.templateget<Term>()*samples[index]; } }; (add_direction.templateoperator()<Terms>(),...); returnresult; } } template<PressureBoundaryFormulationFormulation,typenameTraces> voidapply_residual_rows(constPressureBoundary<Formulation, Traces>&boundary,conststd::vector<SurfaceLinearization<Formulation>>&linearizations,::mfem::Vector&result) { usingnamespaceutils::errors; detail::validate_boundary_output(boundary,result); detail::validate_boundary_samples(boundary,linearizations); for(constauto&point:linearizations) { serif_ensure<SERiFErrorCode::NON_FINITE_VALUE_ERROR, NonFiniteValue>(std::isfinite(point.residual),"Thepressure-boundaryresidualcontainsanon-finitevalue;rejectthiscandidate."); } for(intindex=0;index<boundary.selected_rows->size();++index) { result[boundary.selected_rows->reduced_dofs()[index]]=linearizations[index].residual; } } template<PressureBoundaryFormulationFormulation,typenameTraces,utils::dependencies::IsDependencyContextDirections> requiresutils::dependencies::SatisfiesKeyList<typenameDirections::Bindings,typenameFormulation::StateTerms> voidapply_jacobian_rows(constPressureBoundary<Formulation, Traces>&boundary,conststd::vector<SurfaceLinearization<Formulation>>&linearizations,constDirections&directions,::mfem::Vector&result) { detail::validate_boundary_output(boundary,result); detail::validate_boundary_samples(boundary,linearizations); const::mfem::Vectorvalues=detail::boundary_jacobian_action(boundary,linearizations,directions,typenameFormulation::StateTerms{}); detail::replace_boundary_rows(boundary,values,result); } template<PressureBoundaryFormulationFormulation,typenameTraces> voidmask_residual_dual(constPressureBoundary<Formulation, Traces>&boundary,const::mfem::Vector&dual,::mfem::Vector&volume_dual) { detail::validate_boundary_output(boundary,dual); boundary.selected_rows->binding().validate_values(dual); volume_dual=dual; for(constintrow:boundary.selected_rows->reduced_dofs()) { volume_dual[row]=0.0; } } template<typenameTerm,PressureBoundaryFormulationFormulation,typenameTraces> requiresutils::dependencies::BindingsWithBinding<typenameTraces::Bindings,Term> voidadd_jacobian_transpose_rows(constPressureBoundary<Formulation, Traces>&boundary,conststd::vector<SurfaceLinearization<Formulation>>&linearizations,const::mfem::Vector&dual,::mfem::Vector&result) { usingnamespaceutils::errors; detail::validate_boundary_output(boundary,dual); detail::validate_boundary_samples(boundary,linearizations); boundary.selected_rows->binding().validate_values(dual); constauto&trace=boundary.traces.templateget<Term>(); trace.binding().validate_values(result); ::mfem::Vectorweights(boundary.selected_rows->size()); for(intindex=0;index<weights.Size();++index) { weights[index]=linearizations[index].field_derivatives.templateget<Term>()*dual[boundary.selected_rows->reduced_dofs()[index]]; } serif_ensure<SERiFErrorCode::NON_FINITE_VALUE_ERROR, NonFiniteValue>(utils::checks::is_finite(weights),"Thepressure-boundarytransposeproducednon-finiteweights;rejectthiscandidate."); trace.interpolation().AddMultTranspose(weights,result); serif_ensure<SERiFErrorCode::NON_FINITE_VALUE_ERROR, NonFiniteValue>(utils::checks::is_finite(result),"Thepressure-boundarytransposeproducedanon-finiteresult;discardthisoutput."); } }