86 std::optional<KrylovExponentialDiagnostics<uni20::make_real_t<Scalar>>>
diagnostics;
94 throw std::overflow_error(
"Krylov exponential problem dimension exceeds the supported int range");
96 return std::min(
static_cast<int>(problem_dimension), 30);
104 throw std::overflow_error(
"Krylov exponential problem dimension exceeds the supported int range");
106 return std::min(
static_cast<int>(problem_dimension), 64);
109template <uni20::Real Scalar>
116template <uni20::Real Scalar>
118 std::size_t problem_dimension)
132template <uni20::Real Scalar>
Scalar exponential_breakdown_tolerance(KrylovExponentialParams<Scalar>
const& params)
134 return params.breakdown_tolerance >
Scalar{} ? params.breakdown_tolerance
138template <uni20::Real Scalar>
void validate_krylov_exponential_params(KrylovExponentialParams<Scalar>
const& params)
140 if (params.krylov_dimension < 0)
142 throw std::invalid_argument(
"Krylov exponential requires a non-negative krylov_dimension");
144 if (params.minimum_krylov_dimension < 0)
146 throw std::invalid_argument(
"Krylov exponential requires a non-negative minimum_krylov_dimension");
148 if (params.relative_tolerance < Scalar{} || !
uni20::isfinite(params.relative_tolerance))
150 throw std::invalid_argument(
"Krylov exponential requires a finite non-negative relative_tolerance");
152 if (params.estimate_safety_factor < Scalar{1} || !
uni20::isfinite(params.estimate_safety_factor))
154 throw std::invalid_argument(
"Krylov exponential requires estimate_safety_factor >= 1");
156 if (params.breakdown_tolerance < Scalar{} || !
uni20::isfinite(params.breakdown_tolerance))
158 throw std::invalid_argument(
"Krylov exponential requires a finite non-negative breakdown_tolerance");
162template <uni20::Real Scalar>
163[[nodiscard]]
int effective_exponential_minimum_krylov_dimension(KrylovExponentialParams<Scalar>
const& params,
166 int const minimum = params.minimum_krylov_dimension > 0 ? params.minimum_krylov_dimension : 1;
167 if (minimum > basis_limit)
169 throw std::invalid_argument(
"Krylov exponential requires minimum_krylov_dimension <= krylov_dimension");
174template <uni20::Real Scalar>
175[[nodiscard]] Scalar hermitian_exponential_target_error(KrylovExponentialParams<Scalar>
const& params,
182 Scalar
const target = params.relative_tolerance * initial_norm;
185 throw std::overflow_error(
"Krylov exponential relative tolerance target overflowed");
190template <uni20::Real Scalar>
191[[nodiscard]]
bool exponential_estimate_satisfies_target(Scalar
estimate, Scalar target_error,
192 KrylovExponentialParams<Scalar>
const& params)
198 return estimate <= target_error / params.estimate_safety_factor;
201template <uni20::Real Real,
typename TimeScalar>
uni20::complex<Real> exponential_time_as_complex(TimeScalar time)
213template <uni20::Real Real,
typename TimeScalar>
bool hermitian_time_is_unitary(TimeScalar time)
219 return real_part <= tolerance;
222template <uni20::Real Real,
typename TimeScalar>
223void validate_hermitian_adaptive_error_model(KrylovExponentialParams<Real>
const& params, TimeScalar time)
229 if (params.assume_nonexpansive || hermitian_time_is_unitary<Real>(time))
233 throw std::invalid_argument(
234 "Hermitian Krylov adaptive tolerance requires a nonexpansive action; use pure imaginary time or set "
235 "assume_nonexpansive when the caller has verified the model");
238template <uni20::RealOrComplex Scalar,
typename Vector>
struct HermitianExponentialProjection
240 std::vector<Vector> basis;
249 int max_reorthogonalization_passes = 0;
251 bool happy_breakdown =
false;
254template <uni20::Real Real>
256 std::vector<Real>
const& subdiagonal)
258 if (diagonal.size() > 0 && subdiagonal.size() + 1 != diagonal.size())
260 throw std::invalid_argument(
"Hermitian Krylov tridiagonal data have inconsistent sizes");
264 for (std::size_t i = 0; i < diagonal.size(); ++i)
266 projected[i, i] = diagonal[i];
267 if (i + 1 < diagonal.size())
269 projected[i, i + 1] = subdiagonal[i];
270 projected[i + 1, i] = subdiagonal[i];
276template <uni20::RealOrComplex Scalar,
typename Vector, KrylovMatrixFreeOperator<Vector, Scalar> Ops>
277void record_exponential_basis_orthogonality(Ops& ops, HermitianExponentialProjection<Scalar, Vector>& projection)
280 Real frobenius_squared{};
281 for (std::size_t
row = 0;
row < projection.basis.size(); ++
row)
283 for (std::size_t col =
row; col < projection.basis.size(); ++col)
285 Scalar
const entry = ops.inner_product(projection.basis[
row], projection.basis[col]);
289 projection.basis_max_diag_error = std::max(projection.basis_max_diag_error, error);
295 projection.basis_max_offdiag = std::max(projection.basis_max_offdiag, magnitude);
303template <uni20::RealOrComplex Scalar,
typename Vector, KrylovMatrixFreeOperator<Vector, Scalar> Ops,
304 typename StopPredicate>
305HermitianExponentialProjection<Scalar, Vector>
306hermitian_exponential_projection(Ops& ops, Vector
const& initial,
308 StopPredicate&& stop)
312 if (basis_limit <= 0)
314 throw std::invalid_argument(
"Hermitian Krylov exponential requires a positive Krylov dimension");
316 if (basis_limit >
static_cast<int>(problem_dimension))
318 throw std::invalid_argument(
"Hermitian Krylov exponential requires krylov_dimension <= problem dimension");
321 Real const breakdown_tolerance = exponential_breakdown_tolerance(params);
323 HermitianExponentialProjection<Scalar, Vector> result;
324 result.basis.reserve(
static_cast<std::size_t
>(basis_limit));
325 std::vector<Real> diagonal;
326 std::vector<Real> subdiagonal;
327 diagonal.reserve(
static_cast<std::size_t
>(basis_limit));
328 subdiagonal.reserve(
static_cast<std::size_t
>(std::max(0, basis_limit - 1)));
329 LanczosOrthogonalizationDiagnostics<Real> orthogonalization_diagnostics;
330 auto* orthogonalization_diagnostics_ptr =
333 Vector start = ops.allocate_like(initial);
334 ops.copy(start, initial);
335 result.initial_norm = norm_or_inner_product<Scalar>(ops, start);
336 if (result.initial_norm ==
Real{})
340 result.happy_breakdown =
true;
343 ops.scal(start, Scalar{1} /
static_cast<Scalar
>(result.initial_norm));
344 result.basis.push_back(std::move(start));
346 for (
int step = 0; step < basis_limit; ++step)
348 Vector residual = ops.allocate_like(result.basis[
static_cast<std::size_t
>(step)]);
349 ops.matvec(residual, result.basis[
static_cast<std::size_t
>(step)]);
354 ops.axpy(residual, -
static_cast<Scalar
>(subdiagonal[
static_cast<std::size_t
>(step - 1)]),
355 result.basis[
static_cast<std::size_t
>(step - 1)]);
358 Real const projection_scale = detail::hermitian_projection_scale<Scalar>(ops, residual);
359 Real const alpha = detail::hermitian_projection_scalar(
360 ops.inner_product(result.basis[
static_cast<std::size_t
>(step)], residual), projection_scale);
361 diagonal.push_back(alpha);
362 ops.axpy(residual, -
static_cast<Scalar
>(alpha), result.basis[
static_cast<std::size_t
>(step)]);
365 detail::orthogonalize_lanczos_residual<Scalar>(ops, result.basis, residual, orthogonalization_diagnostics_ptr);
366 result.residual_norm =
beta;
367 bool const happy_breakdown =
beta <= breakdown_tolerance;
368 bool const accepted = stop(result.initial_norm, diagonal, subdiagonal,
beta, happy_breakdown);
369 if (accepted || step + 1 == basis_limit || happy_breakdown)
371 result.happy_breakdown = happy_breakdown;
375 ops.scal(residual, Scalar{1} /
static_cast<Scalar
>(
beta));
376 subdiagonal.push_back(
beta);
377 result.basis.push_back(std::move(residual));
380 result.projected = make_hermitian_projected_tridiagonal(diagonal, subdiagonal);
383 result.max_reorthogonalization_correction = orthogonalization_diagnostics.max_reorthogonalization_correction;
384 result.max_reorthogonalization_correction_ratio =
385 orthogonalization_diagnostics.max_reorthogonalization_correction_ratio;
386 result.max_reorthogonalization_passes = orthogonalization_diagnostics.max_reorthogonalization_passes;
387 record_exponential_basis_orthogonality<Scalar>(ops, result);
392template <uni20::RealOrComplex Scalar,
typename Vector, KrylovMatrixFreeOperator<Vector, Scalar> Ops>
393HermitianExponentialProjection<Scalar, Vector>
394hermitian_exponential_projection(Ops& ops, Vector
const& initial,
399 bool)
static {
return false; };
400 return hermitian_exponential_projection<Scalar>(ops, initial, params, basis_limit, never_stop);
403template <uni20::RealOrComplex Scalar,
typename Vector, KrylovMatrixFreeOperator<Vector, Scalar> Ops>
404Vector combine_exponential_basis(Ops& ops, Vector
const& prototype, std::vector<Vector>
const& basis,
405 std::vector<Scalar>
const& coefficients, std::size_t basis_count)
407 if (basis.size() < basis_count || basis_count != coefficients.size())
409 throw std::invalid_argument(
"Krylov exponential basis and coefficient sizes do not match");
412 Vector
action = ops.allocate_like(prototype);
413 ops.set_zero(action);
414 for (std::size_t i = 0; i < basis_count; ++i)
416 if (coefficients[i] != Scalar{})
418 ops.axpy(action, coefficients[i], basis[i]);
424template <
typename Scalar>
427 std::vector<Scalar> coefficients(
static_cast<std::size_t
>(exponential.
rows()));
435template <uni20::RealOrComplex Scalar>
439 std::vector<Scalar> coefficients(
static_cast<std::size_t
>(exponential.
rows()));
442 coefficients[
row] =
static_cast<Scalar
>(
scale * exponential[
row, 0]);
447template <uni20::RealOrComplex Scalar>
449 std::vector<Scalar>
const& coefficients)
455 if (coefficients.empty())
462template <uni20::Real Real>
467 std::size_t
const dimension = eigensystem.eigenvalues.size();
469 for (std::size_t col = 0; col < dimension; ++col)
471 Real const weight = eigensystem.eigenvectors[dimension - 1, col] * eigensystem.eigenvectors[0, col];
477template <uni20::Real Real,
typename TimeScalar>
479 Real residual_norm, TimeScalar time)
481 if (projected.
rows() != projected.
cols())
483 throw std::invalid_argument(
"Hermitian Krylov defect integral requires a square projected matrix");
485 if (projected.
rows() == 0 || initial_norm ==
Real{} || residual_norm ==
Real{})
492 if (time_magnitude ==
Real{})
497 std::size_t
const dimension =
static_cast<std::size_t
>(projected.
rows());
498 std::vector<Real> diagonal(dimension);
499 std::vector<Real> subdiagonal(dimension > 0 ? dimension - 1 : 0);
500 for (std::size_t i = 0; i < dimension; ++i)
502 diagonal[i] = projected[i, i];
503 if (i + 1 < dimension)
505 subdiagonal[i] = projected[i + 1, i];
519 constexpr int panel_count = 1024;
520 static_assert(panel_count % 2 == 0);
524 for (
int panel = 1; panel < panel_count; ++panel)
526 Real const theta =
static_cast<Real>(panel) /
static_cast<Real>(panel_count);
529 weight *
static_cast<Real>(
uni20::math::abs(projected_defect_delta(eigensystem, complex_time, theta)));
532 Real const integral = weighted_sum / (
Real{3} *
static_cast<Real>(panel_count));
533 return initial_norm * residual_norm * time_magnitude * integral;
536template <
typename TimeScalar, uni20::LapackScalar OutputScalar,
typename InputScalar>
537 requires std::constructible_from<OutputScalar, TimeScalar>
542 OutputScalar
const coefficient =
static_cast<OutputScalar
>(time);
547 scaled[
row, col] = coefficient *
static_cast<OutputScalar
>(projected[
row, col]);
555template <uni20::RealOrComplex Scalar,
typename Vector>
556KrylovExponentialDiagnostics<uni20::make_real_t<Scalar>>
557make_exponential_diagnostics(KrylovExponentialResult<Scalar, Vector>
const& result)
559 return KrylovExponentialDiagnostics<uni20::make_real_t<Scalar>>{
560 .op_count = result.matvec_count,
561 .projected_dimension = result.projected_dimension,
562 .initial_norm = result.initial_norm,
563 .final_residual_norm = result.final_residual_norm,
564 .target_error = result.target_error,
565 .error_estimate = result.error_estimate,
566 .endpoint_defect_estimate = result.endpoint_defect_estimate,
567 .defect_integral_estimate = result.defect_integral_estimate,
568 .converged = result.converged};
571template <uni20::RealOrComplex Scalar,
typename Vector>
572void attach_exponential_diagnostics(KrylovExponentialResult<Scalar, Vector>& result,
KrylovDiagnosticsLevel level,
580 result.diagnostics = diagnostics;
583template <uni20::RealOrComplex Scalar,
typename Vector>
584void attach_exponential_diagnostics(KrylovExponentialResult<Scalar, Vector>& result,
KrylovDiagnosticsLevel level)
586 attach_exponential_diagnostics(result, level, make_exponential_diagnostics(result));
590 KrylovMatrixFreeOperator<Vector, Scalar> Ops>
591KrylovExponentialResult<Scalar, Vector>
592make_hermitian_exponential_result(Ops& ops, Vector
const& initial,
593 HermitianExponentialProjection<Scalar, Vector>
const& projection, TimeScalar time,
597 using ProjectedScalar = std::conditional_t<uni20::Complex<Scalar>, Scalar,
Real>;
600 projected_exponential<TimeScalar, ProjectedScalar>(projection.projected, time);
601 std::vector<Scalar>
const coefficients =
602 first_column_scaled(exponential,
static_cast<ProjectedScalar
>(projection.initial_norm));
603 Vector
action = combine_exponential_basis<Scalar>(ops, initial, projection.basis, coefficients, coefficients.size());
604 Real const endpoint_defect = endpoint_defect_estimate<Scalar>(projection.residual_norm, coefficients);
605 Real const defect_integral = hermitian_projected_defect_integral_estimate(
606 projection.projected, projection.initial_norm, projection.residual_norm, time);
607 Real const target_error = hermitian_exponential_target_error(params, projection.initial_norm);
609 projection.happy_breakdown || exponential_estimate_satisfies_target(defect_integral, target_error, params);
611 KrylovExponentialResult<Scalar, Vector> result{.action = std::move(action),
612 .error_estimate = defect_integral,
613 .endpoint_defect_estimate = endpoint_defect,
614 .defect_integral_estimate = defect_integral,
615 .initial_norm = projection.initial_norm,
616 .final_residual_norm = projection.residual_norm,
617 .target_error = target_error,
618 .projected_dimension =
static_cast<int>(projection.projected.rows()),
619 .matvec_count = projection.op_count,
621 .happy_breakdown = projection.happy_breakdown,
622 .diagnostics = std::nullopt};
623 auto diagnostics = make_exponential_diagnostics(result);
624 diagnostics.basis_max_diag_error = projection.basis_max_diag_error;
625 diagnostics.basis_max_offdiag = projection.basis_max_offdiag;
626 diagnostics.basis_frobenius_error = projection.basis_frobenius_error;
627 diagnostics.max_reorthogonalization_correction = projection.max_reorthogonalization_correction;
628 diagnostics.max_reorthogonalization_correction_ratio = projection.max_reorthogonalization_correction_ratio;
629 diagnostics.max_reorthogonalization_passes = projection.max_reorthogonalization_passes;
630 attach_exponential_diagnostics(result, params.diagnostics, diagnostics);
655 KrylovMatrixFreeOperator<Vector, Scalar> Ops>
656 requires(std::constructible_from<uni20::make_real_t<Scalar>, TimeScalar> ||
658KrylovExponentialResult<Scalar, Vector>
664 detail::validate_krylov_exponential_params(params);
665 detail::validate_hermitian_adaptive_error_model(params, time);
668 int const minimum_dimension = detail::effective_exponential_minimum_krylov_dimension(params, basis_limit);
671 auto adaptive_stop = [&](
Real initial_norm, std::vector<Real>
const& diagonal, std::vector<Real>
const& subdiagonal,
672 Real residual_norm,
bool happy_breakdown) {
673 if (!adaptive || happy_breakdown ||
static_cast<int>(diagonal.size()) < minimum_dimension)
679 detail::hermitian_projected_defect_integral_estimate(projected, initial_norm, residual_norm, time);
680 Real const target_error = detail::hermitian_exponential_target_error(params, initial_norm);
681 return detail::exponential_estimate_satisfies_target(
estimate, target_error, params);
684 auto projection = detail::hermitian_exponential_projection<Scalar>(ops, initial, params, basis_limit, adaptive_stop);
685 if (projection.initial_norm ==
Real{})
687 Vector
action = ops.allocate_like(initial);
688 ops.set_zero(action);
689 KrylovExponentialResult<Scalar, Vector> result{.action = std::move(action),
690 .initial_norm = projection.initial_norm,
691 .final_residual_norm = projection.residual_norm,
692 .target_error =
Real{},
693 .projected_dimension = 0,
694 .matvec_count = projection.op_count,
696 .happy_breakdown =
true,
697 .diagnostics = std::nullopt};
698 detail::attach_exponential_diagnostics(result, params.diagnostics);
702 auto result = detail::make_hermitian_exponential_result<Scalar>(ops, initial, projection, time, params);
703 if (adaptive && !result.converged && params.throw_on_nonconvergence)
705 throw std::runtime_error(
"Hermitian Krylov exponential did not satisfy the requested relative_tolerance");
721 KrylovMatrixFreeOperator<Vector, Scalar> Ops>
722 requires(std::constructible_from<uni20::make_real_t<Scalar>, TimeScalar> ||
724KrylovExponentialResult<Scalar, Vector>
730 detail::validate_krylov_exponential_params(params);
733 throw std::invalid_argument(
"Nonsymmetric Krylov exponential adaptive relative_tolerance is not implemented yet");
736 std::size_t
const problem_dimension =
739 if (basis_limit <= 0)
741 throw std::invalid_argument(
"nonsymmetric Krylov exponential requires a positive Krylov dimension");
743 if (basis_limit >
static_cast<int>(problem_dimension))
745 throw std::invalid_argument(
"nonsymmetric Krylov exponential requires krylov_dimension <= problem dimension");
748 Vector start = ops.allocate_like(initial);
749 ops.copy(start, initial);
750 Real const initial_norm = norm_or_inner_product<Scalar>(ops, start);
751 if (initial_norm ==
Real{})
754 KrylovExponentialResult<Scalar, Vector> result{.action = std::move(start),
755 .initial_norm = initial_norm,
756 .final_residual_norm =
Real{},
757 .target_error =
Real{},
758 .projected_dimension = 0,
760 .happy_breakdown =
true,
761 .diagnostics = std::nullopt};
762 detail::attach_exponential_diagnostics(result, params.diagnostics);
766 ArnoldiFactorization<Scalar, Vector> factorization =
767 arnoldi_factorize<Scalar>(ops, initial, basis_limit, detail::exponential_breakdown_tolerance(params));
770 std::vector<Scalar>
const coefficients = detail::first_column_scaled(exponential,
static_cast<Scalar
>(initial_norm));
772 detail::combine_exponential_basis<Scalar>(ops, initial, factorization.basis, coefficients, coefficients.size());
773 Real const endpoint_defect = detail::endpoint_defect_estimate<Scalar>(factorization.residual_norm, coefficients);
775 KrylovExponentialResult<Scalar, Vector> result{.action = std::move(action),
776 .error_estimate = endpoint_defect,
777 .endpoint_defect_estimate = endpoint_defect,
778 .initial_norm = initial_norm,
779 .final_residual_norm = factorization.residual_norm,
780 .target_error =
Real{},
781 .projected_dimension = factorization.step_count,
782 .matvec_count = factorization.op_count,
784 .happy_breakdown = factorization.happy_breakdown,
785 .diagnostics = std::nullopt};
786 detail::attach_exponential_diagnostics(result, params.diagnostics);
General-purpose owning tensor with immediate or deferred mdspan metadata.
Definition basic_tensor.hpp:109
auto rows() const noexcept
Return the matrix row count for rank-two tensors.
Definition basic_tensor.hpp:768
auto cols() const noexcept
Return the matrix column count for rank-two tensors.
Definition basic_tensor.hpp:776
Concept for complex scalar types.
Definition scalar_concepts.hpp:75
Concept for scalar types with a configured dense LAPACK backend.
Definition scalar_concepts.hpp:147
Concept for real scalar types (float, double, etc.).
Definition scalar_concepts.hpp:69
Concept for numeric scalar types (integer, real, or complex).
Definition scalar_concepts.hpp:81
typename detail::complex_type< Real >::type complex
Project-level complex scalar spelling.
Definition types.hpp:66
typename make_real< T >::type make_real_t
Alias for the underlying real-valued type of T.
Definition scalar_traits.hpp:168
constexpr bool isfinite(I const &x) noexcept
Returns whether an integer scalar is finite.
Definition math.hpp:121
action
The executable decides whether to calculate or render an informational/error result.
Definition cli.hpp:23
DiagnosticMagnitude< R > magnitude(R const &value)
Definition gmres_diagnostics.hpp:98
Definition block_tensor_vector.hpp:23
KrylovDiagnosticsLevel
Amount of solver-internal diagnostic state to retain.
Definition matrix_free.hpp:37
KrylovExponentialResult< Scalar, Vector > nonsymmetric_krylov_exponential_action(Ops &ops, Vector const &initial, TimeScalar time, KrylovExponentialParams< uni20::make_real_t< Scalar > > const ¶ms={})
Approximate exp(t A) v for a nonsymmetric matrix-free operator.
Definition krylov_exponential.hpp:725
bool exponential_adaptive_acceptance_enabled(KrylovExponentialParams< Scalar > const ¶ms)
Definition krylov_exponential.hpp:110
void laset(uni20::DenseMatrix< Scalar > &matrix, Scalar const &diagonal, Scalar const &off_diagonal, MatrixFill fill)
Set a selected region of a local dense matrix.
Definition dense_linalg.hpp:294
int default_adaptive_exponential_krylov_dimension(std::size_t problem_dimension)
Return the default adaptive Krylov projection cap for exponential actions.
Definition krylov_exponential.hpp:100
int default_exponential_krylov_dimension(std::size_t problem_dimension)
Return the default Krylov projection dimension for exponential actions.
Definition krylov_exponential.hpp:90
int effective_exponential_krylov_dimension(KrylovExponentialParams< Scalar > const ¶ms, std::size_t problem_dimension)
Return the effective Krylov projection dimension for exponential actions.
Definition krylov_exponential.hpp:117
KrylovExponentialResult< Scalar, Vector > hermitian_krylov_exponential_action(Ops &ops, Vector const &initial, TimeScalar time, KrylovExponentialParams< uni20::make_real_t< Scalar > > const ¶ms={})
Approximate exp(t A) v for a Hermitian matrix-free operator.
Definition krylov_exponential.hpp:659
TridiagonalEigensystem< Scalar > symmetric_tridiagonal_eigensystem(std::vector< Scalar > diagonal, std::vector< Scalar > subdiagonal, bool compute_vectors)
Solve a real symmetric tridiagonal eigensystem through LAPACK sterf or steqr.
Definition dense_subspace.hpp:288
std::size_t validate_matrix_free_dimensions(Ops const &ops, Vector const &vector, char const *context)
Validate that an initial/prototype vector matches the matrix-free problem dimension.
Definition matrix_free.hpp:549
uni20::DenseMatrix< Scalar > arnoldi_projected_hessenberg(ArnoldiFactorization< Scalar, Vector > const &factorization)
Copy the square projected Hessenberg block from an Arnoldi factorization.
Definition nonsymmetric_arnoldi.hpp:548
void matrix_exponential(BackendSelector selector, async::Async< OutputTensor > &output, async::Async< InputTensor > const &input, TimeScalar &&time)
Schedule fixed-output matrix exponentiation through an explicit selector.
Definition async/matrix_exponential.hpp:64
constexpr detail::scalar_math::exp_fn exp
Natural exponential with scalar-specific precision handling.
Definition math.hpp:465
constexpr detail::scalar_math::sqrt_fn sqrt
Square root; exact inputs requiring approximation need an explicit finite precision.
Definition math.hpp:461
constexpr detail::scalar_math::abs_fn abs
Absolute value or complex magnitude, preserving the selected scalar implementation.
Definition math.hpp:459
constexpr detail::scalar_math::real_fn real
Read the real component by value; real and integral scalars retain their type.
Definition math.hpp:671
Definition async/async.hpp:26
void scale(Tensor &tensor, Scalar factor)
Multiply every stored numerical block by a scalar in place.
Definition block_tensor_linear.hpp:400
std::ptrdiff_t index_type
Definition types.hpp:19
mpreal beta(mpreal const &a, mpreal const &x)
Real Beta function; positive rational/integer pairs retain exact values.
Definition mpreal_special.hpp:164
Optional diagnostic state for Krylov exponential actions.
Definition krylov_exponential.hpp:48
Scalar target_error
Definition krylov_exponential.hpp:53
Scalar basis_max_offdiag
Definition krylov_exponential.hpp:61
int projected_dimension
Definition krylov_exponential.hpp:50
int op_count
Definition krylov_exponential.hpp:49
Scalar defect_integral_estimate
Time-integrated Hermitian/Lanczos defect estimate; zero for nonsymmetric Arnoldi actions.
Definition krylov_exponential.hpp:59
Scalar error_estimate
Best available action error estimate for the selected Krylov path.
Definition krylov_exponential.hpp:55
Scalar final_residual_norm
Definition krylov_exponential.hpp:52
int max_reorthogonalization_passes
Definition krylov_exponential.hpp:65
Scalar endpoint_defect_estimate
Final-time defect estimate ||v|| h_{m+1,m} |e_m^* exp(t H_m) e_1|.
Definition krylov_exponential.hpp:57
Scalar max_reorthogonalization_correction
Definition krylov_exponential.hpp:63
Scalar basis_frobenius_error
Definition krylov_exponential.hpp:62
Scalar basis_max_diag_error
Definition krylov_exponential.hpp:60
Scalar initial_norm
Definition krylov_exponential.hpp:51
bool converged
Definition krylov_exponential.hpp:66
Scalar max_reorthogonalization_correction_ratio
Definition krylov_exponential.hpp:64
Parameters for Krylov exponential actions.
Definition krylov_exponential.hpp:26
int krylov_dimension
Fixed projection dimension, or adaptive maximum when relative_tolerance > 0.
Definition krylov_exponential.hpp:28
Scalar estimate_safety_factor
Multiplier applied to the error estimate before comparing with the target.
Definition krylov_exponential.hpp:34
bool assume_nonexpansive
Permit adaptive acceptance for Hermitian actions not known automatically to be unitary.
Definition krylov_exponential.hpp:38
bool throw_on_nonconvergence
Throw if adaptive Hermitian acceptance does not reach the requested tolerance.
Definition krylov_exponential.hpp:40
Scalar breakdown_tolerance
Absolute threshold for invariant-subspace breakdown; zero selects a machine default.
Definition krylov_exponential.hpp:36
Scalar relative_tolerance
Relative error target for nonexpansive Hermitian actions; zero keeps fixed-dimension mode.
Definition krylov_exponential.hpp:32
KrylovDiagnosticsLevel diagnostics
Optional diagnostic retention level.
Definition krylov_exponential.hpp:42
int minimum_krylov_dimension
Minimum projection dimension before adaptive acceptance; zero selects 1.
Definition krylov_exponential.hpp:30
Matrix-free approximation to exp(t A) v.
Definition krylov_exponential.hpp:73
uni20::make_real_t< Scalar > endpoint_defect_estimate
Definition krylov_exponential.hpp:76
Vector action
Definition krylov_exponential.hpp:74
uni20::make_real_t< Scalar > initial_norm
Definition krylov_exponential.hpp:79
uni20::make_real_t< Scalar > error_estimate
Definition krylov_exponential.hpp:75
uni20::make_real_t< Scalar > defect_integral_estimate
Time-integrated Hermitian/Lanczos defect estimate; zero for nonsymmetric Arnoldi actions.
Definition krylov_exponential.hpp:78
std::optional< KrylovExponentialDiagnostics< uni20::make_real_t< Scalar > > > diagnostics
Definition krylov_exponential.hpp:86
uni20::make_real_t< Scalar > final_residual_norm
Definition krylov_exponential.hpp:80
bool converged
Definition krylov_exponential.hpp:84
int matvec_count
Definition krylov_exponential.hpp:83
uni20::make_real_t< Scalar > target_error
Definition krylov_exponential.hpp:81
int projected_dimension
Definition krylov_exponential.hpp:82
bool happy_breakdown
Definition krylov_exponential.hpp:85
Project-level numeric limits customization point.
Definition numeric_limits.hpp:16