point_dofs.hpp array cmath serif/discretization/backend/mfem/dof_selection.hpp src/include/serif/discretization/backend/mfem/mfem_backend.hpp src/include/serif/operators/backend/mfem/nodal_inputs.hpp serif serif::discretization serif::discretization::backend serif::discretization::backend::mfem This file contains the implementation of function select_point_dofs. This function is used to select the components from a single H1 vertex in the fixed computational mesh. This is used to implement point constraints in the discretization (e.g. fixed center of mass) Emily M. Boudreaux #pragmaonce #include<array> #include<cmath> #include"serif/discretization/backend/mfem/dof_selection.hpp" namespaceserif::discretization::backend::mfem{ template<blocks::SpatialTermTermT,domain::schema::IsSchemaSchemaT> requires(blocks::SpatialTermTraits<TermT>::family==functional_space::Family::h1) [[nodiscard]]DofSelectionselect_point_dofs( constTermBinding<TermT, SchemaT>&binding, conststd::array<double,3>&position={}, constdoubletolerance=1.0e-12 ){ usingnamespaceutils::errors; //Mostlythestartofthisisjustvalidationdownto... binding.validate(); serif_ensure<SERiFErrorCode::INVALID_ARGUMENT,std::invalid_argument>(std::isfinite(tolerance)&&tolerance>=0.0,"Pointselectionrequiresafinitenonnegativecoordinatetolerance."); for(constdoublecoordinate:position){ serif_ensure<SERiFErrorCode::NON_FINITE_VALUE_ERROR,std::invalid_argument>(std::isfinite(coordinate),"Pointselectionrequiresfinitereferencecoordinates."); } auto&space=binding.space(); for(intelement=0;element<space.GetNE();++element){ serif_ensure<SERiFErrorCode::INVALID_ARGUMENT,std::invalid_argument>(dynamic_cast<const::mfem::NodalFiniteElement*>(space.GetFE(element))!=nullptr,"PointvaluesrequireanodalH1basis;positive/Bernsteincoefficientsarenotnodalvalues."); } //downtohere. //Thenwecomethroughandwetrytofindthevertexthatmatchestherequestedpositionwithinthenumericaltolerance.e.g.wemightpass //apositionof(0,0,0)hereandatoleranceof1e-12andthiswillthenmatchanyvertexwithinaeuclideandistanceof1e-12from(0,0,0) //Therearebetterwaystodothisbutthisworksfornow. intselected_vertex=-1; for(intvertex=0;vertex<binding.mesh().GetNV();++vertex){ std::array<double,3>coordinates; binding.mesh().GetNode(vertex,coordinates.data()); boolmatches=true; for(intaxis=0;axis<3;++axis){ matches=matches&&std::abs(coordinates[axis]-position[axis])<=tolerance; } if(matches){ serif_ensure<SERiFErrorCode::INVALID_ARGUMENT,std::invalid_argument>(selected_vertex<0,"Therequestedpointmatchesmultiplemeshvertices;useauniquematerialpointorasmallertolerance."); selected_vertex=vertex; } } //Notethathereweenforcethattheselectedpositioniswithintoleranceofameshvertex.Afutureimplementationmightconsidersomemore //complexschemethatinvolvesfindingtheboundingelementsandenforcingsomesortofinterpolationscheme. serif_ensure<SERiFErrorCode::INVALID_ARGUMENT,std::invalid_argument>(selected_vertex>=0,"Therequestedpointisnotameshvertex;pointconstraintscurrentlyrequireauniquenodalH1vertex."); //Thenweloopthroughandselectthedofsassociatedwiththeselectedvertexinthereduceddofspaceoftheprovidedtermbinding. //Ifthatpositionisoutsidethesupportofthetermbindingthiswillthrow. ::mfem::Array<int>vertex_dofs,selected; space.GetVertexDofs(selected_vertex,vertex_dofs); serif_ensure<SERiFErrorCode::INVALID_DOF_COUNT,std::invalid_argument>(vertex_dofs.Size()==1,"ApointconstraintrequiresonescalarnodalDOFatitsvertex."); for(intcomponent=0;component<space.GetVDim();++component){ constautoreduced=binding.reduced_dof(space.DofToVDof(vertex_dofs[0],component)); serif_ensure<SERiFErrorCode::INVALID_DOMAIN_ERROR,std::invalid_argument>(reduced.has_value(),"Theselectedpointliesoutsidetheterm'ssupport."); selected.Append(*reduced); } returnDofSelection(binding,selected,true); } }//namespaceserif::discretization::backend::mfem