iterative-solver 0.0
propose_rspace.h
1#ifndef LINEARALGEBRA_SRC_MOLPRO_LINALG_ITSOLV_PROPOSE_RSPACE_H
2#define LINEARALGEBRA_SRC_MOLPRO_LINALG_ITSOLV_PROPOSE_RSPACE_H
3#include <molpro/linalg/itsolv/IterativeSolver.h>
4#include <molpro/linalg/itsolv/helper.h>
5#include <molpro/linalg/itsolv/subspace/Dimensions.h>
6#include <molpro/linalg/itsolv/subspace/ISubspaceSolver.h>
7#include <molpro/linalg/itsolv/subspace/IXSpace.h>
8#include <molpro/linalg/itsolv/subspace/QSpace.h>
9#include <molpro/linalg/itsolv/subspace/gram_schmidt.h>
10#include <molpro/linalg/itsolv/subspace/util.h>
11#include <molpro/linalg/itsolv/util.h>
12#include <molpro/linalg/itsolv/wrap_util.h>
13#include <molpro/profiler/Profiler.h>
14
15#include <format>
16
18
19template <class R>
20void normalise(VecRef<R>& params, array::ArrayHandler<R, R>& handler, Logger& logger, double thresh = 1.0e-14) {
21 for (auto& p : params) {
22 auto dot = handler.dot(p, p);
23 dot = std::sqrt(std::abs(dot));
24 if (dot > thresh) {
25 handler.scal(1. / dot, p);
26 } else {
27 logger.warn("parameter's length is too small for normalisation, dot = " + std::format("{:.2e}", dot));
28 }
29 }
30}
31namespace dspace {
32
41template <typename value_type>
43 const std::vector<int>& remove_qspace, Logger& logger) {
44 logger.trace("construct_projected_solution()");
45 const auto nQd = remove_qspace.size();
46 const auto nSol = solutions.rows();
47 auto solutions_proj = subspace::Matrix<value_type>({nSol, nQd + dims.nD});
48 for (size_t i = 0; i < nSol; ++i) {
49 for (size_t j = 0; j < nQd; ++j) {
50 solutions_proj(i, j) = solutions(i, dims.oQ + remove_qspace[j]);
51 }
52 for (size_t j = 0; j < dims.nD; ++j) {
53 solutions_proj(i, nQd + j) = solutions(i, dims.oD + j);
54 }
55 }
56 logger.debug("nSol, nQd, nD", nSol, nQd, dims.nD);
57 return solutions_proj;
58}
59
74template <typename value_type>
76 const subspace::Matrix<value_type>& overlap,
77 const subspace::Dimensions& dims, const std::vector<int>& remove_qspace,
78 Logger& logger) {
79 logger.trace("construct_projected_solution_overlap()");
80 const auto nSol = solutions_proj.rows();
81 const auto nQd = remove_qspace.size();
82 auto overlap_proj = subspace::Matrix<value_type>({nSol, nSol});
83 for (size_t i = 0; i < nSol; ++i) {
84 for (size_t ii = 0; ii <= i; ++ii) {
85 for (size_t j = 0; j < nQd; ++j) {
86 for (size_t k = 0; k < nQd; ++k) {
87 overlap_proj(i, ii) += solutions_proj(i, j) * solutions_proj(ii, k) *
88 overlap(dims.oQ + remove_qspace[j], dims.oQ + remove_qspace[k]);
89 }
90 for (size_t k = 0; k < dims.nD; ++k) {
91 overlap_proj(i, ii) +=
92 solutions_proj(i, j) * solutions_proj(ii, nQd + k) * overlap(dims.oQ + remove_qspace[j], dims.oD + k);
93 }
94 }
95 for (size_t j = 0; j < dims.nD; ++j) {
96 for (size_t k = 0; k < dims.nD; ++k) {
97 overlap_proj(i, ii) +=
98 solutions_proj(i, nQd + j) * solutions_proj(ii, nQd + k) * overlap(dims.oD + j, dims.oD + k);
99 }
100 for (size_t k = 0; k < nQd; ++k) {
101 overlap_proj(i, ii) +=
102 solutions_proj(i, nQd + j) * solutions_proj(ii, k) * overlap(dims.oD + j, dims.oQ + remove_qspace[k]);
103 }
104 }
105 overlap_proj(ii, i) = overlap_proj(i, ii);
106 }
107 }
108 return overlap_proj;
109}
110
118template <typename value_type, typename value_type_abs>
120 const value_type_abs norm_thresh, Logger& logger) {
121 logger.trace("remove_null_norm_and_normalise()");
122 const auto nSol = parameters.rows();
123 auto norm_proj = std::vector<value_type_abs>(nSol, 0.);
124 for (size_t i = 0; i < nSol; ++i)
125 norm_proj[i] = std::sqrt(std::abs(overlap(i, i)));
126 for (size_t i = 0, j = 0; i < nSol; ++i) {
127 if (norm_proj[i] > norm_thresh) {
128 parameters.row(j).scal(1. / norm_proj[i]);
129 overlap.col(j).scal(1. / norm_proj[i]);
130 overlap.row(j).scal(1. / norm_proj[i]);
131 ++j;
132 } else {
133 parameters.remove_row(j);
134 overlap.remove_row_col(j, j);
135 std::stringstream ss;
136 ss << std::setprecision(3) << "remove projected solution parameter i = " << i << ", norm = " << norm_proj[i];
137 logger.info(ss.str());
138 }
139 }
140 logger.data_dump("norm = ", norm_proj);
141 logger.data_dump("parameters after normalisation = ", parameters);
142 logger.data_dump("overlap of parameters = ", overlap);
143}
144
157template <typename value_type, typename value_type_abs>
159 const subspace::Matrix<value_type>& overlap_proj, const value_type_abs svd_thresh,
160 Logger& logger) {
161 logger.trace("remove_null_projected_solutions()");
162 logger.debug("nS on entry = ", solutions_proj.rows());
163 value_type* m = const_cast<std::vector<value_type>&>(overlap_proj.data()).data();
164 auto svd_vecs = svd_system(overlap_proj.rows(), overlap_proj.cols(), array::Span(m, overlap_proj.size()),
165 std::numeric_limits<value_type_abs>::max(), true);
166 svd_vecs.remove_if([&svd_thresh](const auto& el) { return el.value < svd_thresh; });
167 svd_vecs.sort([](const auto& lt, const auto& rt) { return lt.value < rt.value; });
168 const auto nD = svd_vecs.size();
169 const auto nX = solutions_proj.cols();
170 auto solutions_stable = subspace::Matrix<value_type>({nD, nX});
171 auto svd = svd_vecs.begin();
172 for (size_t i = 0; i < nD; ++i, ++svd)
173 for (size_t j = 0; j < overlap_proj.cols(); ++j)
174 for (size_t k = 0; k < nX; ++k)
175 solutions_stable(i, k) += svd->v[j] * solutions_proj(j, k);
176 logger.debug("nS without null space = ", solutions_stable.rows());
177 return solutions_stable;
178}
179
189template <typename value_type>
191 const subspace::Dimensions& dims, const std::vector<int>& remove_qspace,
192 const subspace::Matrix<value_type>& overlap, const size_t nR) {
193 const auto nDnew = solutions_proj.rows();
194 const auto nQd = remove_qspace.size();
195 const auto nQ = dims.nQ - nQd;
196 auto ov = overlap;
197 for (size_t i = 0; i < dims.nD; ++i) {
198 ov.remove_row_col(dims.oD, dims.oD);
199 }
200 auto is_Qdelete = [&remove_qspace](size_t i) {
201 return std::find(begin(remove_qspace), end(remove_qspace), i) != end(remove_qspace);
202 };
203 for (size_t i = 0, j = 0; i < dims.nQ; ++i) {
204 if (is_Qdelete(i))
205 ov.remove_row_col(dims.oQ + j, dims.oQ + j);
206 else
207 ++j;
208 }
209 const auto oDnew = dims.nP + nQ + nR;
210 ov.resize({oDnew + nDnew, oDnew + nDnew});
211 /*
212 * append overlap with solutions_proj
213 * x_i = \sum_j c_ij v_j
214 * <x_i, v_j> = \sum_k c_ik <v_k, v_j>
215 * <x_i, x_j> = \sum_kl c_ik c_jl <v_k, v_l>
216 */
217 auto accumulate_ov_offdiag = [&](size_t i, size_t j, size_t jj) {
218 for (size_t k = 0; k < nQd; ++k)
219 ov(oDnew + i, j) += solutions_proj(i, k) * overlap(jj, dims.oQ + remove_qspace[k]);
220 for (size_t k = 0; k < dims.nD; ++k)
221 ov(oDnew + i, j) += solutions_proj(i, nQd + k) * overlap(jj, dims.oD + k);
222 ov(j, oDnew + i) = ov(oDnew + i, j);
223 };
224 for (size_t i = 0; i < nDnew; ++i) {
225 for (size_t j = 0; j < dims.nP; ++j)
226 accumulate_ov_offdiag(i, j, dims.oP + j);
227 for (size_t j = 0, jj = 0; j < dims.nQ; ++j)
228 if (!is_Qdelete(j))
229 accumulate_ov_offdiag(i, dims.nP + jj++, dims.oQ + j);
230 for (size_t j = 0; j < nR; ++j)
231 accumulate_ov_offdiag(i, dims.nP + nQ + j, dims.nX + j);
232 }
233 for (size_t i = 0; i < nDnew; ++i) {
234 for (size_t j = 0; j <= i; ++j) {
235 for (size_t k = 0; k < nQd; ++k) {
236 for (size_t l = 0; l < nQd; ++l)
237 ov(oDnew + i, oDnew + j) += solutions_proj(i, k) * solutions_proj(j, l) *
238 overlap(dims.oQ + remove_qspace[k], dims.oQ + remove_qspace[l]);
239 for (size_t l = 0; l < dims.nD; ++l)
240 ov(oDnew + i, oDnew + j) +=
241 solutions_proj(i, k) * solutions_proj(j, nQd + l) * overlap(dims.oQ + remove_qspace[k], dims.oD + l);
242 }
243 for (size_t k = 0; k < dims.nD; ++k) {
244 for (size_t l = 0; l < nQd; ++l)
245 ov(oDnew + i, oDnew + j) +=
246 solutions_proj(i, nQd + k) * solutions_proj(j, l) * overlap(dims.oD + k, dims.oQ + remove_qspace[l]);
247 for (size_t l = 0; l < dims.nD; ++l)
248 ov(oDnew + i, oDnew + j) +=
249 solutions_proj(i, nQd + k) * solutions_proj(j, nQd + l) * overlap(dims.oD + k, dims.oD + l);
250 }
251 ov(oDnew + j, oDnew + i) = ov(oDnew + i, oDnew + j);
252 }
253 }
254 return ov;
255}
256} // namespace dspace
257
270template <class R, class Q, class P, typename value_type>
272 const CVecRef<P>& pparams, const CVecRef<Q>& qparams, const CVecRef<Q>& dparams,
273 ArrayHandlers<R, Q, P>& handlers, Logger& logger) {
274 logger.trace("append_overlap_with_r()");
275 const auto nP = pparams.size(), nQ = qparams.size(), nD = dparams.size(), nN = params.size();
276 const auto nX = nP + nQ + nD + nN;
277 const auto oP = 0;
278 const auto oQ = oP + nP;
279 const auto oD = oQ + nQ;
280 const auto oN = oD + nD;
281 auto ov = overlap;
282 ov.resize({nX, nX}); // solutions are last
283 ov.slice({oN, oN}, {oN + nN, oN + nN}) = subspace::util::overlap(params, handlers.rr());
284 ov.slice({oN, oP}, {oN + nN, oP + nP}) = subspace::util::overlap(params, pparams, handlers.rp());
285 ov.slice({oN, oQ}, {oN + nN, oQ + nQ}) = subspace::util::overlap(params, qparams, handlers.rq());
286 ov.slice({oN, oD}, {oN + nN, oD + nD}) = subspace::util::overlap(params, dparams, handlers.rq());
287 auto copy_upper_to_lower = [&ov, oN, nN](size_t oX, size_t nX) {
288 for (size_t i = 0; i < nX; ++i)
289 for (size_t j = 0; j < nN; ++j)
290 ov(oX + i, oN + j) = ov(oN + j, oX + i);
291 };
292 copy_upper_to_lower(oP, nP);
293 copy_upper_to_lower(oQ, nQ);
294 copy_upper_to_lower(oD, nD);
295 logger.data_dump("full overlap P+Q+D+R = ", ov);
296 return ov;
297}
298
307template <typename value_type>
308auto limit_qspace_size(const subspace::Dimensions& dims, const size_t max_size_qspace,
309 const subspace::Matrix<value_type>& solutions, Logger& logger) {
310 logger.trace("limit_qspace_size()");
311 using value_type_abs = decltype(std::abs(solutions(0, 0)));
312 auto q_delete = std::vector<int>{};
313 auto q_indices = std::vector<int>(dims.nQ);
314 std::iota(begin(q_indices), end(q_indices), 0);
315 const auto nSol = solutions.rows();
316 while (q_indices.size() > max_size_qspace) {
317 auto max_contrib_to_solution = std::vector<value_type_abs>{};
318 for (auto i : q_indices) {
319 auto contrib = std::vector<value_type_abs>(nSol);
320 for (size_t j = 0; j < nSol; ++j)
321 contrib[j] = std::abs(solutions(j, dims.oQ + i));
322 max_contrib_to_solution.emplace_back(*std::max_element(begin(contrib), end(contrib)));
323 }
324 auto it_min = std::min_element(begin(max_contrib_to_solution), end(max_contrib_to_solution));
325 auto i = std::distance(begin(max_contrib_to_solution), it_min);
326 q_delete.push_back(q_indices.at(i));
327 q_indices.erase(begin(q_indices) + i);
328 logger.debug("contribution to solutions =", max_contrib_to_solution);
329 logger.debug("delete Q i = ", i);
330 }
331 return q_delete;
332}
333
345template <class R, class Q, class P, typename value_type, typename value_type_abs>
347 const std::vector<int>& q_delete, const value_type_abs norm_thresh,
348 const value_type_abs svd_thresh, array::ArrayHandler<Q, Q>& handler, Logger& logger) {
349 const auto dims = xspace.dimensions();
350 const auto overlap = xspace.data.at(subspace::EqnData::S);
351 auto solutions_proj = dspace::construct_projected_solution(solutions, dims, q_delete, logger);
352 auto overlap_proj = dspace::construct_projected_solutions_overlap(solutions_proj, overlap, dims, q_delete, logger);
353 dspace::remove_null_norm_and_normalise(solutions_proj, overlap_proj, norm_thresh, logger);
354 solutions_proj = dspace::remove_null_projected_solutions(solutions_proj, overlap_proj, svd_thresh, logger);
355 overlap_proj = dspace::construct_projected_solutions_overlap(solutions_proj, overlap, dims, q_delete, logger);
356 dspace::remove_null_norm_and_normalise(solutions_proj, overlap_proj, norm_thresh, logger);
357 auto overlap_full_subspace = dspace::construct_full_subspace_overlap(solutions_proj, dims, q_delete, overlap, 0);
358 auto svd_vecs = svd_system(overlap_full_subspace.rows(), overlap_full_subspace.cols(),
359 array::Span(&overlap_full_subspace(0, 0), overlap_full_subspace.size()), svd_thresh, true);
360 assert(svd_vecs.empty() && "P+Q+D subspace should be stable by construction");
361 const auto nD = solutions_proj.rows();
362 const auto nQd = q_delete.size();
363 assert(nQd + dims.nD == solutions_proj.cols());
364 const auto &qparams = xspace.cparamsq(), qactions = xspace.cactionsq();
365 const auto &dparams = xspace.cparamsd(), dactions = xspace.cactionsd();
366 std::vector<Q> dparams_new, dactions_new;
367 {
368 // FIXME need a simpler mechanism for constructing null parameters
369 Q const* q = nullptr;
370 if (!qparams.empty())
371 q = &qparams.front().get();
372 else if (!dparams.empty())
373 q = &dparams.front().get();
374 if (q) {
375 for (size_t i = 0; i < nD; ++i) {
376 dparams_new.emplace_back(handler.copy(*q));
377 dactions_new.emplace_back(handler.copy(*q));
378 handler.fill(0, dparams_new.back());
379 handler.fill(0, dactions_new.back());
380 }
381 }
382 }
383 for (size_t i = 0; i < nD; ++i) {
384 for (size_t j = 0; j < q_delete.size(); ++j) {
385 handler.axpy(solutions_proj(i, j), qparams.at(q_delete[j]), dparams_new.at(i));
386 handler.axpy(solutions_proj(i, j), qactions.at(q_delete[j]), dactions_new.at(i));
387 }
388 for (size_t j = 0; j < dims.nD; ++j) {
389 handler.axpy(solutions_proj(i, nQd + j), dparams.at(j), dparams_new.at(i));
390 handler.axpy(solutions_proj(i, nQd + j), dactions.at(j), dactions_new.at(i));
391 }
392 }
393 for (size_t i = 0; i < nD; ++i) {
394 auto norm = std::sqrt(std::abs(handler.dot(dparams_new.at(i), dparams_new.at(i))));
395 if (norm < norm_thresh) {
396 logger.warn(std::format("construct_dspace: skipping normalisation of D vector {} with near-zero norm = {:.2e}",
397 i, norm));
398 continue;
399 }
400 handler.scal(1. / norm, dparams_new[i]);
401 handler.scal(1. / norm, dactions_new[i]);
402 }
403 return std::make_tuple(std::move(dparams_new), std::move(dactions_new));
404}
405
422template <class R, class Q, class P, typename value_type, typename value_type_abs>
424 const subspace::Dimensions& dims, const CVecRef<P>& pparams, const CVecRef<Q>& qparams,
425 const CVecRef<Q>& dparams, const value_type_abs norm_thresh,
426 ArrayHandlers<R, Q, P>& handlers, Logger& logger) {
427 logger.trace("modified_gram_schmidt()");
428 const auto nR = rparams.size(), nP = pparams.size(), nQ = qparams.size(), nD = dparams.size();
429 // std::cout << "modified_gram_schmidt() nR="<<nR<<" nQ="<<nQ<<" nD="<<nD<<std::endl;
430 assert(nP == dims.nP && nQ == dims.nQ && nD == dims.nD);
431 auto orthogonalise = [&overlap, &rparams, nR](const auto& xparams, auto& handler, const size_t oX, const size_t nX) {
432 for (size_t i = 0; i < nX; ++i) {
433 auto norm = std::abs(overlap(oX + i, oX + i));
434 if (nR > 0) {
435 auto dot_mat = handler.gemm_inner(cwrap(rparams), cwrap_arg(xparams.at(i).get()));
436 std::pair<size_t, size_t> mcoeff_dim = std::make_pair(1, nR);
437 subspace::Matrix<double> mcoeff(dot_mat.data(), mcoeff_dim);
438 for (size_t j = 0; j < nR; ++j) {
439 mcoeff(0, j) = -mcoeff(0, j) / norm;
440 }
441 handler.gemm_outer(mcoeff, cwrap_arg(xparams.at(i).get()), rparams);
442 }
443 }
444 };
445 auto prof = molpro::Profiler::single();
446 prof->start("orthoganalise");
447 orthogonalise(pparams, handlers.rp(), dims.oP, nP);
448 orthogonalise(qparams, handlers.rq(), dims.oQ, nQ);
449 orthogonalise(dparams, handlers.rq(), dims.oD, nD);
450 prof->stop();
451 prof->start("get null_params");
452 auto null_params = std::vector<int>{};
453 for (size_t i = 0; i < nR; ++i) {
454 auto norm = std::sqrt(std::abs(handlers.rr().dot(rparams[i], rparams[i])));
455 if (norm > norm_thresh) {
456 handlers.rr().scal(1. / norm, rparams[i]);
457 for (size_t j = i + 1; j < nR; ++j) {
458 auto ov = handlers.rr().dot(rparams[i], rparams[j]);
459 handlers.rr().axpy(-ov, rparams[i], rparams[j]);
460 }
461 } else {
462 null_params.push_back(i);
463 }
464 }
465 prof->stop();
466 return null_params;
467}
468
470template <class R>
471auto get_new_working_set(const std::vector<int>& working_set, const CVecRef<R>& params, const CVecRef<R>& wparams) {
472 auto new_indices = find_ref(wparams, params);
473 auto new_working_set = std::vector<int>{};
474 for (auto i : new_indices) {
475 new_working_set.emplace_back(working_set.at(i));
476 }
477 return new_working_set;
478}
479
508template <class R, class Q, class P, typename value_type_abs>
509auto propose_rspace(IterativeSolver<R, Q, P>& solver, const VecRef<R>& parameters, const VecRef<R>& residuals,
511 ArrayHandlers<R, Q, P>& handlers, Logger& logger, value_type_abs svd_thresh,
512 value_type_abs res_norm_thresh, int max_size_qspace, molpro::profiler::Profiler& profiler) {
513 // auto prof = profiler.push("itsolv::propose_rspace"); // FIXME two separate profilers
514 auto prof = molpro::Profiler::single();
515 logger.trace("itsolv::detail::propose_rspace");
516 logger.trace("dimensions {nP, nQ, nD, nW} = ", xspace.dimensions().nP, xspace.dimensions().nQ,
517 xspace.dimensions().nD, solver.working_set().size());
518 profiler.start("itsolv::ISubspaceSolver::solutions");
519 auto solutions = subspace_solver.solutions();
520 profiler.stop();
521 auto q_delete = limit_qspace_size(xspace.dimensions(), max_size_qspace, solutions, logger);
522 logger.debug("delete Q parameter indices = ", q_delete);
523 if (!q_delete.empty()) {
524 auto prof = profiler.push("construct_dspace");
525 auto [dparams, dactions] =
526 construct_dspace(solutions, xspace, q_delete, res_norm_thresh, svd_thresh, handlers.qq(), logger);
527 std::sort(begin(q_delete), end(q_delete), std::greater<int>());
528 for (auto iq : q_delete)
529 xspace.eraseq(iq);
530 auto wdparams = wrap(dparams);
531 auto wdactions = wrap(dactions);
532 xspace.update_dspace(wdparams, wdactions);
533 auto eigenvalues_ref = subspace_solver.eigenvalues();
534 subspace_solver.solve(xspace, solutions.rows());
535 auto eigval_error = std::vector<double>{};
536 std::transform(std::begin(eigenvalues_ref), std::end(eigenvalues_ref), std::begin(subspace_solver.eigenvalues()),
537 std::back_inserter(eigval_error), [](auto& e_ref, auto& e_new) { return std::abs(e_ref - e_new); });
538 logger.debug("eigenvalue error due to new D space = ", eigval_error);
539 // FIXME Optionally, solve the subspace problem again and get an estimate of the error due to new D
540 }
541 // Use modified GS to orthonormalise z against P+Q+D, removing any null parameters.
542 auto wresidual = wrap(residuals.begin(), residuals.begin() + solver.working_set().size());
543 profiler.start("normalise");
544 normalise(wresidual, handlers.rr(), logger);
545 profiler.stop();
546 profiler.start("append_overlap_with_r");
547 prof->start("append_overlap_with_r");
548 const auto full_overlap =
549 append_overlap_with_r(xspace.data.at(subspace::EqnData::S), cwrap(wresidual), xspace.cparamsp(),
550 xspace.cparamsq(), xspace.cparamsd(), handlers, logger);
551 profiler.stop();
552 prof->stop();
553 prof->start("redundant_indices");
554 auto redundant_indices =
555 redundant_parameters(full_overlap, xspace.dimensions().nX, wresidual.size(), svd_thresh, logger);
556 prof->stop();
557 logger.debug("redundant indices = ", redundant_indices);
558 util::delete_parameters(redundant_indices, wresidual);
559 profiler.start("modified_gram_schmidt");
560 prof->start("modified_gram_schmidt");
561 auto null_param_indices =
562 modified_gram_schmidt(wresidual, xspace.data.at(subspace::EqnData::S), xspace.dimensions(), xspace.cparamsp(),
563 xspace.cparamsq(), xspace.cparamsd(), res_norm_thresh, handlers, logger);
564 profiler.stop();
565 prof->stop();
566 // Now that there is SVD null_param_indices should always be empty
567 logger.debug("null parameters = ", null_param_indices);
568 util::delete_parameters(null_param_indices, wresidual);
569 normalise(wresidual, handlers.rr(), logger);
570 for (size_t i = 0; i < wresidual.size(); ++i)
571 handlers.rr().copy(parameters.at(i), wresidual.at(i));
572 profiler.start("get_new_working_set");
573 auto new_working_set = get_new_working_set(solver.working_set(), cwrap(residuals), cwrap(wresidual));
574 profiler.stop();
575 return new_working_set;
576}
577} // namespace molpro::linalg::itsolv::detail
578
579#endif // LINEARALGEBRA_SRC_MOLPRO_LINALG_ITSOLV_PROPOSE_RSPACE_H
Enhances various operations between pairs of arrays and allows dynamic code injection with uniform in...
Definition: ArrayHandler.h:162
virtual value_type dot(const AL &x, const AR &y)=0
virtual void scal(value_type alpha, AL &x)=0
virtual AL copy(const AR &source)=0
virtual void axpy(value_type alpha, const AR &x, AL &y)=0
virtual void fill(value_type alpha, AL &x)=0
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
auto & qq()
Definition: ArrayHandlers.h:40
auto & rp()
Definition: ArrayHandlers.h:44
auto & rr()
Definition: ArrayHandlers.h:39
auto & rq()
Definition: ArrayHandlers.h:42
Base class defining the interface common to all iterative solvers.
Definition: IterativeSolver.h:202
virtual const std::vector< int > & working_set() const =0
Working set of roots that are not yet converged.
Definition: Logger.h:428
void info(std::string_view message, Ts &&...args) const
Definition: Logger.h:491
void warn(std::string_view message, Ts &&...args) const
Definition: Logger.h:496
void debug(std::string_view message, Ts &&...args) const
Definition: Logger.h:486
void data_dump(std::string_view what, Ts...data) const
Definition: Logger.h:512
void trace(std::string_view message, Ts &&...args) const
Definition: Logger.h:481
virtual CVecRef< Q > cparamsq() const =0
virtual CVecRef< P > cparamsp() const =0
virtual CVecRef< Q > cactionsd() const =0
SubspaceData data
Equation data in the subspace.
Definition: IXSpace.h:28
virtual void eraseq(size_t i)=0
Removes parameter i from Q subspace.
virtual CVecRef< Q > cactionsq() const =0
virtual CVecRef< Q > cparamsd() const =0
virtual const Dimensions & dimensions() const =0
virtual void update_dspace(VecRef< Q > &params, VecRef< Q > &actions)=0
Updates D space with the new parameters.
Slice row(size_t i)
Access row slice.
Definition: Matrix.h:120
void remove_row(index_type row)
removes a row from the matrix
Definition: Matrix.h:144
const std::vector< T > & data() const &
Access the underlying data buffer.
Definition: Matrix.h:67
size_t size() const
Definition: Matrix.h:170
index_type rows() const
Definition: Matrix.h:167
index_type cols() const
Definition: Matrix.h:168
Profiler & start(const std::string &name)
Profiler & stop(const std::string &name="")
Proxy push(const std::string &name)
static std::shared_ptr< Profiler > single()
auto construct_projected_solutions_overlap(const subspace::Matrix< value_type > &solutions_proj, const subspace::Matrix< value_type > &overlap, const subspace::Dimensions &dims, const std::vector< int > &remove_qspace, Logger &logger)
Constructs overlap matrix for projected solutions.
Definition: propose_rspace.h:75
auto remove_null_projected_solutions(const subspace::Matrix< value_type > &solutions_proj, const subspace::Matrix< value_type > &overlap_proj, const value_type_abs svd_thresh, Logger &logger)
Transforms to a stable subspace of projected solutions via SVD.
Definition: propose_rspace.h:158
void remove_null_norm_and_normalise(subspace::Matrix< value_type > &parameters, subspace::Matrix< value_type > &overlap, const value_type_abs norm_thresh, Logger &logger)
Removes parameters with norm less than threshold and normalises the rest.
Definition: propose_rspace.h:119
auto construct_full_subspace_overlap(const subspace::Matrix< value_type > &solutions_proj, const subspace::Dimensions &dims, const std::vector< int > &remove_qspace, const subspace::Matrix< value_type > &overlap, const size_t nR)
Constructs overlap matrix of P+Q+R+(projected solutions) subspaces, where Q is without removed parame...
Definition: propose_rspace.h:190
auto construct_projected_solution(const subspace::Matrix< value_type > &solutions, const subspace::Dimensions &dims, const std::vector< int > &remove_qspace, Logger &logger)
Projects solution from the full subspace on to Q_{delete} and current D space.
Definition: propose_rspace.h:42
Definition: helper-implementation.h:613
auto limit_qspace_size(const subspace::Dimensions &dims, const size_t max_size_qspace, const subspace::Matrix< value_type > &solutions, Logger &logger)
Ensures that size Q space is within limit by proposing Q parameters for deletion.
Definition: propose_rspace.h:308
void normalise(const size_t n_roots, const VecRef< R > &params, const VecRef< R > &actions, array::ArrayHandler< R, R > &handler, Logger &logger)
Definition: IterativeSolverTemplate.h:84
auto propose_rspace(IterativeSolver< R, Q, P > &solver, const VecRef< R > &parameters, const VecRef< R > &residuals, subspace::IXSpace< R, Q, P > &xspace, subspace::ISubspaceSolver< R, Q, P > &subspace_solver, ArrayHandlers< R, Q, P > &handlers, Logger &logger, value_type_abs svd_thresh, value_type_abs res_norm_thresh, int max_size_qspace, molpro::profiler::Profiler &profiler)
Proposes new parameters for the subspace from the preconditioned residuals.
Definition: propose_rspace.h:509
auto get_new_working_set(const std::vector< int > &working_set, const CVecRef< R > &params, const CVecRef< R > &wparams)
Returns new working set based on parameters included in wparams.
Definition: propose_rspace.h:471
auto append_overlap_with_r(const subspace::Matrix< value_type > &overlap, const CVecRef< R > &params, const CVecRef< P > &pparams, const CVecRef< Q > &qparams, const CVecRef< Q > &dparams, ArrayHandlers< R, Q, P > &handlers, Logger &logger)
Constructs overlap of the full subspace by appending overlap with new parameters to the overlap of pr...
Definition: propose_rspace.h:271
auto construct_dspace(const subspace::Matrix< value_type > &solutions, const subspace::IXSpace< R, Q, P > &xspace, const std::vector< int > &q_delete, const value_type_abs norm_thresh, const value_type_abs svd_thresh, array::ArrayHandler< Q, Q > &handler, Logger &logger)
Constructs the new D space by projecting the solutions onto Qd+D subspace and ensuring they are well ...
Definition: propose_rspace.h:346
auto modified_gram_schmidt(const VecRef< R > &rparams, const subspace::Matrix< value_type > &overlap, const subspace::Dimensions &dims, const CVecRef< P > &pparams, const CVecRef< Q > &qparams, const CVecRef< Q > &dparams, const value_type_abs norm_thresh, ArrayHandlers< R, Q, P > &handlers, Logger &logger)
Orthogonalises R parameters against P+Q+D subspace (and themselves)
Definition: propose_rspace.h:423
auto redundant_parameters(const subspace::Matrix< value_type > &overlap, const size_t oR, const size_t nR, const value_type_abs svd_thresh, Logger &logger)
Deduces a set of parameters that are redundant due to linear dependencies.
Definition: helper-implementation.h:629
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< double > >
Calculates overlap matrix between left and right vectors.
Definition: util.h:49
void delete_parameters(std::vector< int > indices, Container &params)
Removes parameters.
Definition: util.h:98
auto cwrap(ForwardIt begin, ForwardIt end)
Takes a begin and end iterators and returns a vector of references to each element.
Definition: wrap.h:52
auto cwrap_arg(T &&arg, S &&... args) -> std::enable_if_t< std::conjunction_v< std::is_same< decay_t< T >, decay_t< S > >... >, CVecRef< decay_t< T > > >
Constructs a vector of const reference wrappers with provided arguments.
Definition: wrap.h:149
auto wrap(ForwardIt begin, ForwardIt end)
Takes a begin and end iterators and returns a vector of references to each element.
Definition: wrap.h:32
std::list< SVD< value_type > > svd_system(size_t nrows, size_t ncols, const array::Span< value_type > &m, double threshold, bool hermitian=false, bool reduce_to_rank=false)
Performs singular value decomposition and returns SVD objects for singular values less than threshold...
Definition: helper-implementation.h:268
std::vector< std::reference_wrapper< const A > > CVecRef
Definition: wrap.h:14
std::vector< std::reference_wrapper< A > > VecRef
Definition: wrap.h:11
std::vector< size_t > find_ref(const VecRef< R > &wparams, ForwardIt begin, ForwardIt end)
Given wrapped references in wparams and a range of original parameters [begin, end),...
Definition: wrap_util.h:17
Stores partitioning of XSpace into P, Q and R blocks with sizes and offsets for each one.
Definition: Dimensions.h:8
size_t oQ
Definition: Dimensions.h:16
size_t nD
Definition: Dimensions.h:13
size_t nX
Definition: Dimensions.h:14
size_t nQ
Definition: Dimensions.h:12
size_t nP
Definition: Dimensions.h:11
size_t oP
Definition: Dimensions.h:15
size_t oD
Definition: Dimensions.h:17
Manages solution of the subspace problem and storage of those solutions.
Definition: ISubspaceSolver.h:21
virtual void solve(IXSpace< R, Q, P > &xspace, size_t nroots_max)=0
Solve the subspace problem.
virtual const std::vector< value_type > & eigenvalues() const =0
Access eigenvalues from the last solve() call.
virtual const Matrix< value_type > & solutions() const =0
Access solutions from the last solve() call.