geometry_derivatives.hpp array cmath expected serif/backend/mfem/operators/element_data.hpp serif/backend/mfem/operators/operand_evaluation.hpp serif/backend/mfem/operators/rejection.hpp serif/backend/mfem/operators/workspace.hpp serif/operators/plan.hpp serif/backend/mfem/mapping/domain_mapper.hpp serif/backend/mfem/shared/parallel.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<expected> #include"serif/backend/mfem/operators/element_data.hpp" #include"serif/backend/mfem/operators/operand_evaluation.hpp" #include"serif/backend/mfem/operators/rejection.hpp" #include"serif/backend/mfem/operators/workspace.hpp" #include"serif/operators/plan.hpp" #include"serif/backend/mfem/mapping/domain_mapper.hpp" #include"serif/backend/mfem/shared/parallel.hpp" namespaceserif::operators::backend::mfem{ template<VolumeEquationEquation,typenameContribution> [[nodiscard]]autogeometry_integrand_variation( constElementData<EquationPlan<Equation>::operand_count>&data, intpoint, constmapping::VolumeMappingContext&context, constmapping::VolumeMappingVariation&variation ){ usingPlan=EquationPlan<Equation>; usingTest=OperandEvaluator<equations::TestOperandOf<Contribution>>; typenameTest::Valueresult{}; for(intoutput=0;output<Test::components;++output){ constintrow=point*Test::components+output; doublevalue=data.weighted_residual[row]*variation.weight_variation/context.quadrature.physical_integration_weight; for(intaxis=0;axis<3;++axis){ value+=data.weighted_position_derivative(row,axis)*variation.mapping.physical_position_variation[axis]; } discretization::forms::component(result,output)=value; } Plan::templatefor_each_input<Contribution>([&]<typenameOperand>(Operand,std::size_tindex){ usingEvaluator=OperandEvaluator<Operand>; ifconstexpr(Evaluator::geometry_dependent){ constautodelta=Evaluator::geometry_variation( Evaluator::reference_value(*data.reference_operand_values[index],point),context.mapping,variation.mapping ); for(intoutput=0;output<Test::components;++output){ for(intinput=0;input<Evaluator::components;++input){ discretization::forms::component(result,output)+=data.weighted_field_derivatives( point*Test::components+output,Plan::templatecomponent_offset<Operand>()+input )*discretization::forms::component(delta,input); } } } }); returnresult; } template<VolumeEquationEquation,typenameContribution> [[nodiscard]]std::expected<::mfem::DenseMatrix,PreparationRejection>element_geometry_derivatives( constElementData<EquationPlan<Equation>::operand_count>&data, constdiscretization::backend::mfem::DofMap&displacement_binding, const::mfem::FiniteElementSpace&compactification_space, constmapping::DomainMapper&mapper, Workspace&workspace ){ usingTest=OperandEvaluator<equations::TestOperandOf<Contribution>>; constauto&element=*displacement_binding.space().GetFE(data.element); workspace.element_values=data.geometry->displacement; constautobase=mapping::element_displacement_data_from_element_vdofs(element,workspace.element_values); constmapping::ElementCompactificationDatacompactification( *compactification_space.GetFE(data.element),data.geometry->compactification ); constmapping::ElementMappingDatamapping_data{base,compactification}; ::mfem::IsoparametricTransformationtransformation; ::serif::utils::parallel::element_transformation(*displacement_binding.space().GetMesh(),data.element,transformation); constintpoints=data.basis->rule->GetNPoints(); ::mfem::DenseMatrixresult(points*Test::reference_components,12); constmapping::DMReferenceDisplacementSamplesample{workspace.displacement_value,workspace.displacement_gradient}; mapping::CompactificationPointDatacompactification_sample; ::mfem::DenseMatrixinverse_mesh_jacobian(3); for(intpoint=0;point<points;++point){ data.geometry->mapping.load(point,workspace.mapping_context); //Alltwelvedirectionssharetheinversefixed-meshJacobian,thecompactificationsample //andthephysicaltestvaluesatthispoint. ::mfem::Mult(workspace.mapping_context.quadrature.J_element_to_physical_inverse, workspace.mapping_context.mapping.mapping_jacobian,inverse_mesh_jacobian); constmapping::CompactificationPointData*fixed_sample=nullptr; if(workspace.mapping_context.mapping.compactified){ constautostatus=mapper.evaluate_compactification_coordinate( compactification,transformation,data.basis->rule->IntPoint(point), workspace.mapping_workspace,compactification_sample,&inverse_mesh_jacobian ); if(status!=mapping::MappingStatus::VALID){ returnstd::unexpected(PreparationRejection{ .reason=PreparationRejectionReason::MAPPING,.mapping_status=status, .element=data.element,.quadrature_point=point, .message="Invalidfixedcompactificationsampleforanequationderivative." }); } fixed_sample=&compactification_sample; } std::array<typenameTest::Value,Test::reference_components>tests; for(inttest_component=0;test_component<Test::reference_components;++test_component){ typenameTest::ReferenceValuereference{}; discretization::forms::component(reference,test_component)=1.0; tests[test_component]=Test::physical_value(reference,workspace.mapping_context.mapping); } for(intcomponent=0;component<12;++component){ workspace.displacement_value=0.0; workspace.displacement_gradient=0.0; if(component%4==0){ workspace.displacement_value[component/4]=1.0; }else{ workspace.displacement_gradient(component/4,component%4-1)=1.0; } constautostatus=mapper.evaluate_volume_direction_variation( mapping_data,base,transformation,data.basis->rule->IntPoint(point), workspace.mapping_context,workspace.mapping_workspace,workspace.mapping_variation,sample,fixed_sample, inverse_mesh_jacobian ); if(status!=mapping::MappingStatus::VALID){ returnstd::unexpected(PreparationRejection{ .reason=PreparationRejectionReason::MAPPING,.mapping_status=status, .element=data.element,.quadrature_point=point, .message="Invalidlocaldisplacementderivativeofanequation." }); } constautophysics=geometry_integrand_variation<Equation, Contribution>( data,point,workspace.mapping_context,workspace.mapping_variation ); for(inttest_component=0;test_component<Test::reference_components;++test_component){ typenameTest::ReferenceValuereference{}; discretization::forms::component(reference,test_component)=1.0; constauto&test=tests[test_component]; constautotest_variation=Test::geometry_variation(reference,workspace.mapping_context.mapping,workspace.mapping_variation.mapping); doublevalue=0.0; for(intoutput=0;output<Test::components;++output){ value+=discretization::forms::component(test,output)*discretization::forms::component(physics,output) +data.weighted_residual[point*Test::components+output]*discretization::forms::component(test_variation,output); } if(!std::isfinite(value)){ returnstd::unexpected(PreparationRejection{ .reason=PreparationRejectionReason::NON_FINITE,.element=data.element, .quadrature_point=point,.message="Non-finitelocaldisplacementderivativeofanequation." }); } result(point*Test::reference_components+test_component,component)=value; } } } returnresult; } }//namespaceserif::operators::backend::mfem