actions.hpp algorithm concepts span serif/geometry/deformation/failure.hpp serif/geometry/deformation/detail/action_storage.hpp serif/geometry/deformation/spaces.hpp serif/geometry/deformation/workspace.hpp src/compile_time_checks/serif/geometry/deformation.cpp src/compile_time_checks/serif/geometry/deformation_meanfield.cpp src/include/serif/geometry/deformation/composition.hpp src/include/serif/geometry/deformation/deformation.hpp src/include/serif/geometry/deformation/linearization.hpp serif serif::geometry serif::geometry::deformation #pragmaonce #include<algorithm> #include<concepts> #include<span> #include"serif/geometry/deformation/failure.hpp" #include"serif/geometry/deformation/detail/action_storage.hpp" #include"serif/geometry/deformation/spaces.hpp" #include"serif/geometry/deformation/workspace.hpp" namespaceserif::geometry::deformation { template<typenameMap> inlineconstexprboolis_linear_deformation=requires { requiresMap::is_linear; }; template<typenameMap> conceptDeformationDimensions=requires(constMap&map) { typenameMap::Workspace; typenameMap::InputSpace; typenameMap::OutputSpace; {map.input_size()}->std::same_as<std::size_t>; {map.output_size()}->std::same_as<std::size_t>; }; template<typenameMap> conceptLinearDeformationMap=DeformationDimensions<Map>&&is_linear_deformation<Map>&& (std::same_as<DeformationWorkspace<Map>,EmptyDeformationWorkspace>||requires(constMap&map) { {map.make_workspace()}->std::same_as<DeformationWorkspace<Map>>; })&&requires(constMap&map,std::span<constdouble>input,std::span<double>output,DeformationWorkspace<Map>&workspace) { {map.apply(input,output,workspace)}->std::same_as<DeformationStatus>; {map.apply_transpose(input,output,workspace)}->std::same_as<DeformationStatus>; }; template<typenameMap> conceptDifferentiableDeformationMap=DeformationDimensions<Map>&&requires(constMap&map,std::span<constdouble>state,std::span<constdouble>direction,std::span<constdouble>dual,std::span<double>output,DeformationWorkspace<Map>&workspace) { {map.make_workspace()}->std::same_as<DeformationWorkspace<Map>>; {map.build_displacement(state,output,workspace)}->std::same_as<DeformationStatus>; {map.apply_jacobian(state,direction,output,workspace)}->std::same_as<DeformationStatus>; {map.apply_jacobian_transpose(state,dual,output,workspace)}->std::same_as<DeformationStatus>; {map.apply_pullback_derivative(state,direction,dual,output,workspace)}->std::same_as<DeformationStatus>; }; template<typenameMap> conceptDeformationMap=LinearDeformationMap<Map>||DifferentiableDeformationMap<Map>; template<DeformationMapMap> [[nodiscard]]DeformationWorkspace<Map>make_deformation_workspace(constMap&map) { ifconstexpr(requires{map.make_workspace();}) { returnmap.make_workspace(); } else { return{}; } } template<DeformationMapMap> [[nodiscard]]DeformationStatusbuild_displacement(constMap&map,std::span<constdouble>parameters,std::span<double>displacement,DeformationWorkspace<Map>&workspace) { if(constautostatus=detail::validate_disjoint_output(displacement,{parameters});!status) { returnstatus; } ifconstexpr(LinearDeformationMap<Map>) { returnmap.apply(parameters,displacement,workspace); } else { returnmap.build_displacement(parameters,displacement,workspace); } } template<DeformationMapMap> [[nodiscard]]DeformationStatusapply_jacobian(constMap&map,std::span<constdouble>parameters,std::span<constdouble>direction,std::span<double>displacement_direction,DeformationWorkspace<Map>&workspace) { if(constDeformationStatusstatus=detail::validate_action_arguments(displacement_direction,map.output_size(),{{parameters,map.input_size()}});!status) { returnstatus; } if(constDeformationStatusstatus=detail::validate_disjoint_output(displacement_direction,{direction});!status) { returnstatus; } ifconstexpr(LinearDeformationMap<Map>) { returnmap.apply(direction,displacement_direction,workspace); } else { returnmap.apply_jacobian(parameters,direction,displacement_direction,workspace); } } template<DeformationMapMap> [[nodiscard]]DeformationStatusapply_jacobian_transpose(constMap&map,std::span<constdouble>parameters,std::span<constdouble>displacement_dual,std::span<double>parameter_dual,DeformationWorkspace<Map>&workspace) { if(constDeformationStatusstatus=detail::validate_action_arguments(parameter_dual,map.input_size(),{{parameters,map.input_size()}});!status) { returnstatus; } if(constDeformationStatusstatus=detail::validate_disjoint_output(parameter_dual,{displacement_dual});!status) { returnstatus; } ifconstexpr(LinearDeformationMap<Map>) { returnmap.apply_transpose(displacement_dual,parameter_dual,workspace); } else { returnmap.apply_jacobian_transpose(parameters,displacement_dual,parameter_dual,workspace); } } template<DeformationMapMap> [[nodiscard]]DeformationStatusapply_pullback_derivative(constMap&map,std::span<constdouble>parameters,std::span<constdouble>direction,std::span<constdouble>displacement_dual,std::span<double>parameter_dual,DeformationWorkspace<Map>&workspace) { if(constDeformationStatusstatus=detail::validate_action_arguments(parameter_dual,map.input_size(),{{parameters,map.input_size()},{direction,map.input_size()},{displacement_dual,map.output_size()}});!status) { returnstatus; } ifconstexpr(is_linear_deformation<Map>) { std::ranges::fill(parameter_dual,0.0); return{}; } else { returnmap.apply_pullback_derivative(parameters,direction,displacement_dual,parameter_dual,workspace); } } }//namespaceserif::geometry::deformation