deformation.hpp limits memory span utility serif/geometry/deformation/linearization.hpp vector serif/backend/mfem/operators/actions.hpp serif/backend/mfem/shared/parallel.hpp serif/utils/error/errors.hpp src/include/serif/backend/mfem/model/computations/shape_derivatives.hpp src/lib/serif/backend/mfem/model/deformation.cpp serif::model::backend::mfem::ShapeDerivatives serif::model::backend::mfem::LinearizedBlock serif serif::discretization serif::discretization::backend serif::discretization::backend::mfem serif::model serif::model::backend serif::model::backend::mfem serif::model::backend::mfem::detail #pragmaonce #include<limits> #include<memory> #include<span> #include<utility> #include"serif/geometry/deformation/linearization.hpp" #include<vector> #include"serif/backend/mfem/operators/actions.hpp" #include"serif/backend/mfem/shared/parallel.hpp" #include"serif/utils/error/errors.hpp" namespaceserif::discretization::backend::mfem{ classDofMap; } namespaceserif::model::backend::mfem{ usingoperators::backend::mfem::LinearizedBlock; [[nodiscard]]LinearizedBlockdisplacement_projection(constdiscretization::backend::mfem::DofMap&binding); template<typenameDeformation> structShapeDerivatives{ std::shared_ptr<constDeformation>deformation; LinearizedBlockprojection; LinearizedBlocktangent; }; namespacedetail{ template<geometry::deformation::DeformationMapMap> voidvalidate_deformation(conststd::shared_ptr<constgeometry::deformation::DeformationLinearization<Map>>&state){ usingnamespaceutils::errors; serif_ensure<SERiFErrorCode::INVALID_ARGUMENT>(state&&state->map,"Amodelshapeactionrequiresanaccepteddeformationmap."); serif_ensure<SERiFErrorCode::INVALID_DOF_COUNT>(state->map->input_size()<=static_cast<std::size_t>(std::numeric_limits<int>::max())&&state->map->output_size()<=static_cast<std::size_t>(std::numeric_limits<int>::max()),"DeformationcoordinatecountsexceedtheMFEMintegerrange."); serif_ensure<SERiFErrorCode::INVALID_DOF_COUNT>(state->parameters.size()==state->map->input_size(),"Theaccepteddeformationmustcontaineveryshapecoordinate."); } voidrequire_deformation_action(constgeometry::deformation::DeformationStatus&status); }//namespacedetail template<geometry::deformation::DeformationMapMap> [[nodiscard]]LinearizedBlockdeformation_tangent(std::shared_ptr<constgeometry::deformation::DeformationLinearization<Map>>state){ detail::validate_deformation(state); constintrows=static_cast<int>(state->map->output_size()); constintcolumns=static_cast<int>(state->map->input_size()); returnoperators::backend::mfem::linearized_action(rows,columns,[state,workspace=std::make_shared<geometry::deformation::DeformationWorkspace<Map>>(geometry::deformation::make_deformation_workspace(*state->map))](const::mfem::Vector&input,::mfem::Vector&output)mutable{ detail::require_deformation_action(geometry::deformation::apply_jacobian(*state,std::span<constdouble>(input.GetData(),input.Size()),std::span<double>(output.GetData(),output.Size()),*workspace)); },[state,workspace=std::make_shared<geometry::deformation::DeformationWorkspace<Map>>(geometry::deformation::make_deformation_workspace(*state->map))](const::mfem::Vector&input,::mfem::Vector&output)mutable{ detail::require_deformation_action(geometry::deformation::apply_jacobian_transpose(*state,std::span<constdouble>(input.GetData(),input.Size()),std::span<double>(output.GetData(),output.Size()),*workspace)); },[state,workspaces=std::vector<std::shared_ptr<geometry::deformation::DeformationWorkspace<Map>>>{}](std::span<const::mfem::Vector*const>inputs,std::span<::mfem::Vector*const>outputs)mutable{ //Directionsareindependent;eachworkerownsitsworkspace,soeverycolumniscomputedasbyMult. constautoworkers=static_cast<std::size_t>(utils::parallel::worker_count()); while(workspaces.size()<workers){ workspaces.push_back(std::make_shared<geometry::deformation::DeformationWorkspace<Map>>(geometry::deformation::make_deformation_workspace(*state->map))); } utils::parallel::for_each_index(static_cast<int>(inputs.size()),[&](constintindex,constintworker){ constauto&input=*inputs[static_cast<std::size_t>(index)]; auto&output=*outputs[static_cast<std::size_t>(index)]; detail::require_deformation_action(geometry::deformation::apply_jacobian(*state,std::span<constdouble>(input.GetData(),input.Size()),std::span<double>(output.GetData(),output.Size()),*workspaces[static_cast<std::size_t>(worker)])); }); }); } }//namespaceserif::model::backend::mfem