evaluator.cpp serif/backend/mfem/mapping/evaluator.hpp serif/utils/error/errors.hpp serif serif::mapping #include"serif/backend/mfem/mapping/evaluator.hpp" #include"serif/utils/error/errors.hpp" namespaceserif::mapping{ usingnamespaceutils::errors; GridFunctionMappingEvaluator::GridFunctionMappingEvaluator( constDomainMapper&mapper, constmfem::GridFunction&displacement, constmfem::GridFunction&compactification_coordinate ): m_mapper(mapper), m_displacement(displacement), m_compactification_coordinate(compactification_coordinate), m_displacement_space(displacement.FESpace()), m_compactification_space(compactification_coordinate.FESpace()), m_displacement_space_sequence(m_displacement_space!=nullptr?m_displacement_space->GetSequence():-1), m_compactification_space_sequence(m_compactification_space!=nullptr?m_compactification_space->GetSequence():-1), m_workspace(mapper.get_dimension()){ serif_ensure<SERiFErrorCode::MISSING_DISPLACEMENT_FINITE_ELEMENT_SPACE>(m_displacement_space!=nullptr,"Displacementgridfunctionisnotassociatedwithafinite-elementspace."); serif_ensure<SERiFErrorCode::MISSING_DISPLACEMENT_FINITE_ELEMENT_SPACE>(m_compactification_space!=nullptr,"Compactification-coordinategridfunctionisnotassociatedwithafinite-elementspace."); serif_ensure<SERiFErrorCode::MISMATCHED_MESHING_MAPS>(m_displacement_space->GetMesh()==m_compactification_space->GetMesh(),"Displacementandcompactification-coordinategridfunctionsarenotassociatedwiththesamemesh."); serif_ensure<SERiFErrorCode::INVALID_DIMENSION>(m_displacement.VectorDim()==mapper.get_dimension(),"Displacementgridfunctionvectordimensiondoesnotmatchthemapperdimension.({}vs.{})",m_displacement.VectorDim(),mapper.get_dimension()); serif_ensure<SERiFErrorCode::INVALID_COMPACTIFICATION_RANK>(m_compactification_coordinate.VectorDim()==1,"Compactification-coordinategridfunctionmustbeascalarfield.Insteadithasvectordimension{}.",m_compactification_coordinate.VectorDim()); serif_ensure<SERiFErrorCode::INVALID_DIMENSION>(m_displacement_space->GetMesh()->SpaceDimension()==mapper.get_dimension(),"Displacementfinite-elementspacemeshdimensiondoesnotmatchthemapperdimension.({}vs.{})",m_displacement_space->GetMesh()->SpaceDimension(),mapper.get_dimension()); } voidGridFunctionMappingEvaluator::invalidate_cache()noexcept{ m_displacement_data.reset(); m_compactification_data.reset(); m_cached_element_id=-1; } voidGridFunctionMappingEvaluator::validate_field_bindings()const{ serif_ensure<SERiFErrorCode::CACHE_FE_BINDING_ERROR>(m_displacement.FESpace()==m_displacement_space,"Displacementgridfunctionisnolongerassociatedwiththecachedfinite-elementspace."); serif_ensure<SERiFErrorCode::CACHE_FE_BINDING_ERROR>(m_compactification_coordinate.FESpace()==m_compactification_space,"Compactification-coordinategridfunctionisnolongerassociatedwiththecachedfinite-elementspace."); } boolGridFunctionMappingEvaluator::invalidate_for_changed_spaces(){ constlongdisplacement_sequence=m_displacement_space->GetSequence(); constlongcompactification_sequence=m_compactification_space->GetSequence(); if(displacement_sequence==m_displacement_space_sequence&&compactification_sequence==m_compactification_space_sequence){ returnfalse; } invalidate_cache(); m_displacement_space_sequence=displacement_sequence; m_compactification_space_sequence=compactification_sequence; returntrue; } voidGridFunctionMappingEvaluator::refresh(){ validate_field_bindings(); if(invalidate_for_changed_spaces()){ return; } constintelement_id=m_cached_element_id; invalidate_cache(); if(element_id>=0){ load_element(element_id); } } voidGridFunctionMappingEvaluator::load_element(constintelement_id){ validate_field_bindings(); (void)invalidate_for_changed_spaces(); if(element_id==m_cached_element_id){ return; } constmfem::FiniteElementSpace&displacement_space=*m_displacement_space; constmfem::FiniteElementSpace&compactification_space=*m_compactification_space; serif_ensure<SERiFErrorCode::INVALID_ELEMENT_ID_ERROR>(element_id>=0,"ElementIDmustbenon-negative.Instead{}wasprovided.",element_id); serif_ensure<SERiFErrorCode::INVALID_ELEMENT_ID_ERROR>(element_id<displacement_space.GetMesh()->GetNE(),"ElementIDmustbelessthanthenumberofelementsinthemesh({}).Instead{}wasprovided.",displacement_space.GetMesh()->GetNE(),element_id); mfem::DofTransformation*displacement_transformation=displacement_space.GetElementVDofs(element_id,m_displacement_dofs); compactification_space.GetElementDofs(element_id,m_compactification_dofs); m_displacement.GetSubVector(m_displacement_dofs,m_element_displacement); m_compactification_coordinate.GetSubVector(m_compactification_dofs,m_element_compactification); if(displacement_transformation!=nullptr){ displacement_transformation->InvTransformPrimal(m_element_displacement); } constmfem::FiniteElement&displacement_element=*displacement_space.GetFE(element_id); constmfem::FiniteElement&compactification_element=*compactification_space.GetFE(element_id); m_displacement_data=std::make_unique<ElementDisplacementData>(element_displacement_data_from_element_vdofs(displacement_element,m_element_displacement)); m_compactification_data=std::make_unique<ElementCompactificationData>(compactification_element,m_element_compactification); m_cached_element_id=element_id; } MappingStatusGridFunctionMappingEvaluator::evaluate_point(mfem::ElementTransformation&transformation,constmfem::IntegrationPoint&integration_point,MappingPointContext&context){ load_element(transformation.ElementNo); constElementMappingDatadata{ .displacement=*m_displacement_data, .compactification=*m_compactification_data }; returnm_mapper.evaluate_point(data,transformation,integration_point,m_workspace,context); } MappingStatusGridFunctionMappingEvaluator::evaluate_volume(mfem::ElementTransformation&transformation,constmfem::IntegrationPoint&integration_point,VolumeMappingContext&context){ load_element(transformation.ElementNo); constElementMappingDatadata{ .displacement=*m_displacement_data, .compactification=*m_compactification_data }; returnm_mapper.evaluate_volume(data,transformation,integration_point,m_workspace,context); } MappingStatusGridFunctionMappingEvaluator::evaluate_face(mfem::FaceElementTransformations&transformations,FaceElementSideside,constmfem::IntegrationPoint&integration_point,FaceMappingContext&context){ mfem::ElementTransformation*transformation=side==FaceElementSide::ELEMENT_1?transformations.Elem1:transformations.Elem2; serif_ensure<SERiFErrorCode::ELEMENT_NULLPTR_ERROR>(transformation!=nullptr,"Faceevaluationrequestedforasidethatdoesnotexist."); load_element(transformation->ElementNo); constElementMappingDatadata{ .displacement=*m_displacement_data, .compactification=*m_compactification_data }; returnm_mapper.evaluate_face(data,transformations,side,integration_point,m_workspace,context); } }