point_border.hpp serif/operators/backend/mfem/nodal_rows.hpp src/include/serif/model/computations/point_constraints.hpp serif serif::operators serif::operators::backend serif::operators::backend::mfem #pragmaonce #include"serif/operators/backend/mfem/nodal_rows.hpp" namespaceserif::operators::backend::mfem{ template<AffinePointEquationEquationT,discretization::domain::schema::IsSchemaSchemaT> voidvalidate_point_border_outputs( constPointBorderData<EquationT, SchemaT>&data, const::mfem::Vector&carrier, const::mfem::Vector&phase ){ usingnamespaceutils::errors; validate_nodal_output(data.nodal,carrier); data.border_binding.validate(); serif_ensure<SERiFErrorCode::INVALID_DOF_COUNT,std::invalid_argument>( phase.Size()==1,"Pointphaseoutputmustcontainonescalar."); } template<AffinePointEquationEquationT,discretization::domain::schema::IsSchemaSchemaT> voidadd_point_border_residual( constPointBorderData<EquationT, SchemaT>&data, ::mfem::Vector&carrier, ::mfem::Vector&phase ){ validate_point_border_outputs(data,carrier,phase); constintpoint=data.nodal.discretization.selected_rows->reduced_dofs()[0]; carrier[point]+=data.border_coefficient*data.nodal.derivative(0,0); phase[0]=data.nodal.residual[0]; data.nodal.discretization.residual_binding.validate_values(carrier); data.border_binding.validate_values(phase); } template<AffinePointEquationEquationT,discretization::domain::schema::IsSchemaSchemaT,typenameCoefficientsT> voidapply_point_border_jacobian( constPointBorderData<EquationT, SchemaT>&data, constCoefficientsT&direction, ::mfem::Vector&carrier, ::mfem::Vector&phase ){ usingnamespaceutils::errors; validate_point_border_outputs(data,carrier,phase); constauto&input=direction.templateget<typenameEquationT::Test>(); constauto&border=direction.templateget<typenameEquationT::Border>(); serif_ensure<SERiFErrorCode::CACHE_FE_BINDING_ERROR,std::invalid_argument>( &input.binding==&data.nodal.discretization.residual_binding&&&border.binding==&data.border_binding, "Pointborderdirectionsmustusetheacceptedcoefficientbindings."); data.nodal.discretization.residual_binding.validate_values(input.values); data.border_binding.validate_values(border.values); constintpoint=data.nodal.discretization.selected_rows->reduced_dofs()[0]; constdoublecarrier_direction=input.values[point]; constdoubleborder_direction=border.values[0]; carrier[point]+=data.nodal.derivative(0,0)*border_direction; phase[0]=data.nodal.derivative(0,0)*carrier_direction; data.nodal.discretization.residual_binding.validate_values(carrier); data.border_binding.validate_values(phase); } template<AffinePointEquationEquationT,discretization::domain::schema::IsSchemaSchemaT> voidapply_point_border_jacobian_transpose( constPointBorderData<EquationT, SchemaT>&data, const::mfem::Vector&carrier_dual, const::mfem::Vector&phase_dual, ::mfem::Vector&carrier_result, ::mfem::Vector&border_result ){ validate_point_border_outputs(data,carrier_result,border_result); data.nodal.discretization.residual_binding.validate_values(carrier_dual); data.border_binding.validate_values(phase_dual); constintpoint=data.nodal.discretization.selected_rows->reduced_dofs()[0]; constdoublepoint_dual=carrier_dual[point]; constdoublescalar_dual=phase_dual[0]; carrier_result[point]+=data.nodal.derivative(0,0)*scalar_dual; border_result[0]+=data.nodal.derivative(0,0)*point_dual; data.nodal.discretization.residual_binding.validate_values(carrier_result); data.border_binding.validate_values(border_result); } }