1#ifndef LINEARALGEBRA_SRC_MOLPRO_LINALG_ITSOLV_METRICCHECKER_H
2#define LINEARALGEBRA_SRC_MOLPRO_LINALG_ITSOLV_METRICCHECKER_H
4#include <molpro/linalg/array/Span.h>
5#include <molpro/linalg/itsolv/ArrayHandlers.h>
6#include <molpro/linalg/itsolv/subspace/IXSpace.h>
7#include <molpro/linalg/itsolv/subspace/Matrix.h>
8#include <molpro/linalg/itsolv/subspace/util.h>
9#include <molpro/linalg/itsolv/wrap.h>
10#include <molpro/linalg/scalar_traits.h>
27template <
class R,
class Q,
class P>
69 const Q* metric_action_q =
nullptr;
74 q = &xspace.
cparamsq().front().get();
77 }
else if (m_reference) {
79 metric_action_q = &m_reference->metric_action_q;
80 qmq = m_reference->qmq;
88 for (
size_t i = 0;
i < params.size(); ++
i) {
94 throw std::runtime_error(std::format(
"The metric is not Hermitian: <x|M q> = {:.6e} differs from <M x|q> = "
95 "{:.6e} for a new parameter x and a subspace vector q",
96 double(std::abs(
xmq)),
double(std::abs(
mxq))));
109 handlers.qr().copy(m_reference->q, params.front());
123 for (
size_t i = 0;
i <
n; ++
i)
124 for (
size_t j = 0;
j <=
i; ++
j)
127 throw std::runtime_error(
"The metric is not Hermitian: its matrix in the P space is not");
156 using matrix_type = Eigen::Matrix<value_type, Eigen::Dynamic, Eigen::Dynamic>;
157 using row_major_type = Eigen::Matrix<value_type, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>;
158 const auto n = Eigen::Index(
metric.rows());
159 const auto np = Eigen::Index(nP);
160 if (
np == 0 ||
np >=
n)
162 const matrix_type m_rows = Eigen::Map<const row_major_type>(
metric.data().data(),
n,
n);
163 const matrix_type
m = (m_rows + m_rows.adjoint()) /
value_type(2);
164 if (!m_pp_factor || m_pp_factor->rows() !=
np) {
165 const Eigen::LLT<matrix_type>
llt(
m.topLeftCorner(
np,
np));
166 if (
llt.info() != Eigen::Success)
168 m_pp_factor = matrix_type(
llt.matrixL());
171 const matrix_type
schur =
m.bottomRightCorner(
n -
np,
n -
np) -
y.adjoint() *
y;
172 if (Eigen::LLT<matrix_type>(
schur).info() == Eigen::Success)
178 using matrix_type = Eigen::Matrix<value_type, Eigen::Dynamic, Eigen::Dynamic>;
179 using row_major_type = Eigen::Matrix<value_type, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>;
180 const auto n = Eigen::Index(
metric.rows());
183 const matrix_type m_rows = Eigen::Map<const row_major_type>(
metric.data().data(),
n,
n);
184 const matrix_type
m = (m_rows + m_rows.adjoint()) /
value_type(2);
185 if (Eigen::LLT<matrix_type>(
m).info() == Eigen::Success)
187 const matrix_type
s = Eigen::Map<const row_major_type>(overlap.data().data(),
n,
n);
188 const Eigen::SelfAdjointEigenSolver<matrix_type>
s_eigen(
s);
190 Eigen::Index rank = 0;
191 for (Eigen::Index
i = 0;
i <
n; ++
i)
201 Eigen::EigenvaluesOnly);
207 throw std::runtime_error(std::format(
"The metric is not positive definite: it has the Rayleigh quotient {:.3e} "
208 "on the subspace, against a largest one of {:.3e}",
219 std::optional<Reference> m_reference;
221 std::optional<Eigen::Matrix<value_type, Eigen::Dynamic, Eigen::Dynamic>> m_pp_factor;
decltype(value_type_L{} *value_type_R{}) value_type
Definition ArrayHandler.h:182
decltype(check_abs< value_type >()) value_type_abs
Definition ArrayHandler.h:183
Non-owning container taking a pointer to the data buffer and its size and exposing routines for itera...
Definition Span.h:31
Class, containing a collection of array handlers used in IterativeSolver Provides a Builder sub-class...
Definition ArrayHandlers.h:25
Checks that the metric of a generalised problem has the properties that its kind declares,...
Definition MetricChecker.h:28
static void check_positive(const subspace::Matrix< value_type > &metric, const subspace::Matrix< value_type > &overlap)
Definition MetricChecker.h:177
static void check_hermitian(const array::Span< value_type > &matrix, const size_t n)
Checks that the metric matrix in the P space is Hermitian.
Definition MetricChecker.h:121
typename array::ArrayHandler< R, R >::value_type_abs value_type_abs
Definition MetricChecker.h:31
void remember(const CVecRef< R > ¶ms, const CVecRef< R > &metric_actions, const subspace::IXSpace< R, Q, P > &xspace, ArrayHandlers< R, Q, P > &handlers)
Keeps the first new parameter and its action of the metric for the next check_hermitian(),...
Definition MetricChecker.h:104
void reset()
Definition MetricChecker.h:46
static value_type_abs hermiticity_tolerance()
The relative tolerance of the checks of Hermiticity, calibrated for double precision and rescaled to ...
Definition MetricChecker.h:38
void check_hermitian(const CVecRef< R > ¶ms, const CVecRef< R > &metric_actions, const subspace::IXSpace< R, Q, P > &xspace, ArrayHandlers< R, Q, P > &handlers) const
Checks that the metric is Hermitian on new parameters before they are added to the subspace.
Definition MetricChecker.h:66
void reset_pspace()
Forgets the factor of the metric matrix in the P space kept by check_positive_subspace(),...
Definition MetricChecker.h:52
static value_type_abs positivity_tolerance()
Definition MetricChecker.h:42
void check_positive_subspace(const subspace::Matrix< value_type > &metric, const subspace::Matrix< value_type > &overlap, const size_t nP)
Checks that the metric matrix of the subspace is consistent with a positive (semi)definite metric.
Definition MetricChecker.h:154
typename array::ArrayHandler< R, R >::value_type value_type
Definition MetricChecker.h:30
Full subspace.
Definition IXSpace.h:21
SubspaceData< value_type > data
Equation data in the subspace.
Definition IXSpace.h:30
virtual CVecRef< Q > cparamsq() const =0
bool stores_metric_actions() const
Whether the actions of the metric on the Q and D vectors are kept.
Definition IXSpace.h:65
virtual const Dimensions & dimensions() const =0
virtual CVecRef< Q > cmetric_actionsq() const =0
Actions of the metric on the Q space parameters, empty unless there is a metric.
Matrix container that allows simple data access, slicing, copying and resizing without loosing data.
Definition Matrix.h:32
Definition helper-dispatch.h:224
auto overlap(const CVecRef< R > &left, const CVecRef< Q > &right, array::ArrayHandler< Z, W > &handler) -> std::enable_if_t< detail::Z_and_W_are_one_of_R_and_Q< R, Q, Z, W >, Matrix< typename array::ArrayHandler< Z, W >::value_type > >
Calculates overlap matrix between left and right vectors.
Definition util.h:57
std::unique_ptr< LinearEigensystem< R, Q, P > > create_LinearEigensystem(const LinearEigensystemOptions &options, const std::shared_ptr< ArrayHandlers< R, Q, P > > &handlers=std::make_shared< molpro::linalg::itsolv::ArrayHandlers< R, Q, P > >())
Definition SolverFactory.h:111
std::vector< std::reference_wrapper< const A > > CVecRef
Definition wrap.h:14
T conjugate(const T &x)
Complex conjugate, staying within the scalar type; the identity for a real type.
Definition scalar_traits.h:47
size_t nQ
Definition Dimensions.h:13
size_t oQ() const
offset of the Q block
Definition Dimensions.h:18