element_evaluation.hpp array cmath span serif/utils/error/nonfinite.hpp serif/backend/mfem/operators/operand_evaluation.hpp serif/backend/mfem/operators/element_data.hpp serif/backend/mfem/operators/workspace.hpp serif/operators/plan.hpp src/include/serif/backend/mfem/operators/element_transpose.hpp src/include/serif/backend/mfem/operators/volume_application.hpp src/include/serif/backend/mfem/operators/volume_stages.hpp serif serif::operators serif::operators::backend serif::operators::backend::mfem #pragmaonce #include<array> #include<cmath> #include<span> #include"serif/utils/error/nonfinite.hpp" #include"serif/backend/mfem/operators/operand_evaluation.hpp" #include"serif/backend/mfem/operators/element_data.hpp" #include"serif/backend/mfem/operators/workspace.hpp" #include"serif/operators/plan.hpp" namespaceserif::operators::backend::mfem{ template<typenameContributionT,std::size_tCount> voidelement_residual(constElementData<Count>&data,::mfem::Vector&result,BasisWorkspace&workspace){ OperandEvaluator<equations::TestOperandOf<ContributionT>>::integrate(data.geometry->test_basis,data.weighted_residual,result,workspace); } template<VolumeEquationEquationT,typenameContributionT,boolFields,boolGeometry> voidfinish_element_action( constElementData<EquationPlan<EquationT>::operand_count>&data, const::mfem::DenseMatrix&geometry_derivatives, Workspace&workspace, ::mfem::Vector&result ){ usingnamespaceutils::errors; usingTest=OperandEvaluator<equations::TestOperandOf<ContributionT>>; constintpoints=data.basis->rule->GetNPoints(); ifconstexpr(Geometry){ workspace.reference_test_values.SetSize(points*Test::reference_components); //MFEMstoreseachderivativecolumncontiguously;keepthesametwelve-termsum. constintderivative_stride=geometry_derivatives.Height(); constdouble*derivatives=geometry_derivatives.GetData(); constdouble*displacement=workspace.displacement_samples.GetData(); double*values=workspace.reference_test_values.GetData(); for(intpoint=0;point<points;++point){ for(intoutput=0;output<Test::reference_components;++output){ constintrow=point*Test::reference_components+output; doublevalue=0.0; for(intinput=0;input<12;++input){ value+=derivatives[input*derivative_stride+row]*displacement[12*point+input]; } values[row]=value; } } } ifconstexpr(Geometry&&!Test::geometry_dependent){ //Bothtermshavethesametestrepresentation,sooneintegrationissufficient. workspace.quadrature_values+=workspace.reference_test_values; } for(intentry=0;entry<workspace.quadrature_values.Size();++entry){ serif_ensure<SERiFErrorCode::NON_FINITE_VALUE_ERROR,NonFiniteValue>( std::isfinite(workspace.quadrature_values[entry]),"Non-finiteequationJacobianaction." ); } ifconstexpr(Fields||!Test::geometry_dependent){ Test::integrate(data.geometry->test_basis,workspace.quadrature_values,result,workspace.basis); }else{ result.SetSize(data.basis->reference_test_basis.width()); result=0.0; } ifconstexpr(Geometry&&Test::geometry_dependent){ for(intentry=0;entry<workspace.reference_test_values.Size();++entry){ serif_ensure<SERiFErrorCode::NON_FINITE_VALUE_ERROR,NonFiniteValue>( std::isfinite(workspace.reference_test_values[entry]),"Non-finiteequationgeometryaction." ); } data.basis->reference_test_basis.integrate(workspace.reference_test_values,workspace.test_variation_result,workspace.basis); result+=workspace.test_variation_result; } } template<VolumeEquationEquationT,typenameContributionT,boolFields=true,boolGeometry=true> voidelement_jacobian_action( constElementData<EquationPlan<EquationT>::operand_count>&data, const::mfem::DenseMatrix&geometry_derivatives, conststd::array<discretization::backend::mfem::DofMap::Elements,EquationPlan<EquationT>::column_count>&columns, conststd::array<const::mfem::Vector*,EquationPlan<EquationT>::column_count>&directions, constdiscretization::backend::mfem::DofMap::Elements&displacement_binding, const::mfem::Vector&displacement_direction, Workspace&workspace, ::mfem::Vector&result ){ usingPlan=EquationPlan<EquationT>; usingTest=OperandEvaluator<equations::TestOperandOf<ContributionT>>; constintpoints=data.basis->rule->GetNPoints(); workspace.quadrature_values.SetSize(points*Test::components); workspace.quadrature_values=0.0; ifconstexpr(Fields){ Plan::templatefor_each_input<ContributionT>([&]<typenameOperandT>(OperandT,std::size_tindex){ usingEvaluator=OperandEvaluator<OperandT>; constexprautocolumn=Plan::templatecolumn_index<OperandT>(); columns[column].element_values(data.element,*directions[column],workspace.element_values); Evaluator::evaluate(data.geometry->operand_basis[index],workspace.element_values,workspace.operand_values[index],workspace.basis); for(intpoint=0;point<points;++point){ for(intoutput=0;output<Test::components;++output){ constintrow=point*Test::components+output; for(intinput=0;input<Evaluator::components;++input){ workspace.quadrature_values[row]+=data.weighted_field_derivatives(row,Plan::templatecomponent_offset<OperandT>()+input) *workspace.operand_values[index][point*Evaluator::components+input]; } } } }); } ifconstexpr(Geometry){ displacement_binding.element_values(data.element,displacement_direction,workspace.displacement_direction); data.basis->displacement_basis.evaluate(workspace.displacement_direction,workspace.displacement_samples,workspace.basis); } finish_element_action<EquationT, ContributionT, Fields, Geometry>(data,geometry_derivatives,workspace,result); } template<VolumeEquationEquationT,typenameContributionT> voidelement_geometry_actions( constElementData<EquationPlan<EquationT>::operand_count>&data, const::mfem::DenseMatrix&geometry_derivatives, constdiscretization::backend::mfem::DofMap::Elements&displacement_binding, std::span<const::mfem::Vector*const>displacement_directions, Workspace&workspace, std::span<::mfem::Vector*const>results ){ usingTest=OperandEvaluator<equations::TestOperandOf<ContributionT>>; constintlanes=static_cast<int>(displacement_directions.size()); constintpoints=data.basis->rule->GetNPoints(); for(intlane=0;lane<lanes;++lane){ displacement_binding.element_values(data.element,*displacement_directions[static_cast<std::size_t>(lane)],workspace.displacement_direction); constintwidth=workspace.displacement_direction.Size(); workspace.lane_coefficients.SetSize(width*lanes); for(inti=0;i<width;++i){ workspace.lane_coefficients[i*lanes+lane]=workspace.displacement_direction[i]; } } data.basis->displacement_basis.evaluate_many(workspace.lane_coefficients,workspace.lane_samples,lanes,workspace.basis); constintsamples=workspace.lane_samples.Size()/lanes; for(intlane=0;lane<lanes;++lane){ workspace.displacement_samples.SetSize(samples); for(inti=0;i<samples;++i){ workspace.displacement_samples[i]=workspace.lane_samples[i*lanes+lane]; } workspace.quadrature_values.SetSize(points*Test::components); workspace.quadrature_values=0.0; finish_element_action<EquationT, ContributionT, false, true>(data,geometry_derivatives,workspace,*results[static_cast<std::size_t>(lane)]); } } }//namespaceserif::operators::backend::mfem