element_transpose.hpp serif/backend/mfem/operators/element_evaluation.hpp src/include/serif/backend/mfem/operators/volume_application.hpp serif serif::operators serif::operators::backend serif::operators::backend::mfem #pragmaonce #include"serif/backend/mfem/operators/element_evaluation.hpp" namespaceserif::operators::backend::mfem{ template<VolumeEquationEquationT,typenameContributionT> voidelement_jacobian_transpose( constElementData<EquationPlan<EquationT>::operand_count>&data, const::mfem::DenseMatrix&geometry_derivatives, constdiscretization::backend::mfem::DofMap::Elements&row, const::mfem::Vector&residual_dual, Workspace&workspace, std::array<::mfem::Vector,EquationPlan<EquationT>::column_count>&column_duals, ::mfem::Vector&displacement_dual ){ usingnamespaceutils::errors; usingPlan=EquationPlan<EquationT>; usingTest=OperandEvaluator<equations::TestOperandOf<ContributionT>>; for(::mfem::Vector&column:column_duals){ column.SetSize(0); } row.element_values(data.element,residual_dual,workspace.element_values); Test::evaluate(data.geometry->test_basis,workspace.element_values,workspace.test_values,workspace.basis); data.basis->reference_test_basis.evaluate(workspace.element_values,workspace.reference_test_values,workspace.basis); constintpoints=data.basis->rule->GetNPoints(); Plan::templatefor_each_input<ContributionT>([&]<typenameOperandT>(OperandT,std::size_tindex){ usingEvaluator=OperandEvaluator<OperandT>; workspace.operand_dual.SetSize(points*Evaluator::components); for(intpoint=0;point<points;++point){ for(intinput=0;input<Evaluator::components;++input){ doublevalue=0.0; for(intoutput=0;output<Test::components;++output){ constintrow_index=point*Test::components+output; value+=data.weighted_field_derivatives(row_index,Plan::templatecomponent_offset<OperandT>()+input)*workspace.test_values[row_index]; } workspace.operand_dual[point*Evaluator::components+input]=value; } } Evaluator::integrate(data.geometry->operand_basis[index],workspace.operand_dual,workspace.element_result,workspace.basis); auto&column=column_duals[Plan::templatecolumn_index<OperandT>()]; if(column.Size()==0){ column=workspace.element_result; }else{ column+=workspace.element_result; } }); workspace.displacement_dual.SetSize(12*points); //Usethesamestoredcolumnsandcomponentorderastheforwardgeometryaction. constintderivative_stride=geometry_derivatives.Height(); constdouble*derivatives=geometry_derivatives.GetData(); constdouble*test_values=workspace.reference_test_values.GetData(); double*displacement=workspace.displacement_dual.GetData(); for(intpoint=0;point<points;++point){ for(intinput=0;input<12;++input){ doublevalue=0.0; for(intoutput=0;output<Test::reference_components;++output){ constintrow_index=point*Test::reference_components+output; value+=derivatives[input*derivative_stride+row_index]*test_values[row_index]; } serif_ensure<SERiFErrorCode::NON_FINITE_VALUE_ERROR,NonFiniteValue>( std::isfinite(value),"Non-finitegeometryJacobiantransposeaction." ); displacement[12*point+input]=value; } } data.basis->displacement_basis.integrate(workspace.displacement_dual,displacement_dual,workspace.basis); } }//namespaceserif::operators::backend::mfem