Concepts#

namespace pressio{ namespace nonlinearsolvers{

template <class T>
concept NonlinearSystem =
     std::copy_constructible<typename T::state_type>
  && std::copy_constructible<typename T::residual_type>
  && requires(const T & A,
	      const typename T::state_type & state,
	      typename T::residual_type & r)
  {
    { A.createState()       } -> std::same_as<typename T::state_type>;
    { A.createResidual()    } -> std::same_as<typename T::residual_type>;
    { A.residual(state, r)  } -> std::same_as<void>;
  };

template <class T>
concept NonlinearSystemFusingResidualAndJacobian =
     std::copy_constructible<typename T::state_type>
  && std::copy_constructible<typename T::residual_type>
  && std::copy_constructible<typename T::jacobian_type>
  && requires(const T & A,
	      const typename T::state_type & state,
	      typename T::residual_type & r,
	      std::optional<typename T::jacobian_type*> j)
  {
    { A.createState()       } -> std::same_as<typename T::state_type>;
    { A.createResidual()    } -> std::same_as<typename T::residual_type>;
    { A.createJacobian()    } -> std::same_as<typename T::jacobian_type>;
    { A.residualAndJacobian(state, r, j)  } -> std::same_as<void>;
  };

template <class T>
concept RealValuedNonlinearSystem =
  NonlinearSystem<T>
  && std::floating_point< scalar_trait_t<typename T::state_type> >
  && std::floating_point< scalar_trait_t<typename T::residual_type> >;

template <class T>
concept RealValuedNonlinearSystemFusingResidualAndJacobian =
  NonlinearSystemFusingResidualAndJacobian<T>
  && std::floating_point< scalar_trait_t<typename T::state_type> >
  && std::floating_point< scalar_trait_t<typename T::residual_type> >
  && std::floating_point< scalar_trait_t<typename T::jacobian_type> >;


}} // end namespace pressio::nonlinearsolvers