Uni20
Asynchronous tensor and runtime library.
Loading...
Searching...
No Matches
two_site_dmrg.hpp
Go to the documentation of this file.
1
7#pragma once
8
11#include <uni20/core/math.hpp>
20
21#include <algorithm>
22#include <cmath>
23#include <concepts>
24#include <cstddef>
25#include <functional>
26#include <optional>
27#include <stdexcept>
28#include <string_view>
29#include <type_traits>
30#include <utility>
31#include <vector>
32
34{
35
50
66
86
90 static_cast<std::size_t>(TwoSiteDmrgPerformanceEvent::count)>;
91
95 static_cast<std::size_t>(TwoSiteDmrgPerformanceEvent::count)>;
96
101[[nodiscard]] constexpr auto
103{
105 switch (event)
106 {
107 case run:
108 return "run";
109 case sweep:
110 return "sweep";
111 case bond_update:
112 return "bond update";
114 return "center construction";
116 return "local eigensolver";
118 return "effective Hamiltonian application";
120 return "Krylov vector allocation";
122 return "Krylov vector update";
123 case krylov_reduction:
124 return "Krylov reduction";
125 case block_svd:
126 return "block SVD";
127 case svd_sector_batch:
128 return "SVD sector batch";
129 case state_selection:
130 return "state selection";
132 return "factor materialization";
134 return "environment update";
135 case count:
136 break;
137 }
138 std::unreachable();
139}
140
170
173template <uni20::Real Real> struct TwoSiteDmrgRunResult
174{
176 std::vector<TwoSiteDmrgSweepSummary<Real>> sweeps;
179};
180
184template <uni20::Real Real, class InstalledBond> struct TwoSiteDmrgStepResult
185{
187 std::size_t first_site;
199 InstalledBond bond;
200};
201
202namespace detail
203{
204
211template <class Storage, class Scalar>
212concept TwoSiteCenterStorageFor =
215
216template <class Function>
217void execute_materialization_batch(SerialBlockExecution, std::size_t size, Function&& function)
218{
219 for (std::size_t index = 0; index < size; ++index)
220 function(index);
221}
222
223template <class Function>
224void execute_materialization_batch(SchedulerBatchBlockExecution, std::size_t size, Function&& function)
225{
226 async::execute_batch(size, std::forward<Function>(function));
227}
228
238template <BlockTensorStorage OutputStorage, bool StoreAllLegalBlocks, BlockTensorView Input>
239 requires LocalBlockStorageFor<OutputStorage, block_tensor_value_t<Input>,
240 block_tensor_type_t<Input>::key_coordinate_count(),
241 block_tensor_type_t<Input>::dense_block_order()>
242[[nodiscard]] auto materialize_local_block_tensor(Input const& input)
243{
244 using output_type = BlockTensor<block_tensor_value_t<Input>, block_tensor_domain_t<Input>,
245 block_tensor_codomain_t<Input>, OutputStorage>;
246 auto output = [&] {
247 if constexpr (CompleteBlockStorage<OutputStorage>)
248 {
249 if constexpr (requires {
250 output_type(uninitialized, input.symmetry(), input.domain(), input.codomain(),
251 input.allocation_context());
252 })
253 return output_type(uninitialized, input.symmetry(), input.domain(), input.codomain(),
254 input.allocation_context());
255 else
256 return output_type(uninitialized, input.symmetry(), input.domain(), input.codomain());
257 }
258 else
259 {
260 using key_type = typename output_type::key_type;
261 auto keys = [&] {
262 if constexpr (StoreAllLegalBlocks)
263 return input.legal_block_keys();
264 else
265 return std::vector<key_type>(input.stored_keys().begin(), input.stored_keys().end());
266 }();
267 if constexpr (requires {
268 output_type(uninitialized, input.symmetry(), input.domain(), input.codomain(), keys,
269 input.allocation_context());
270 })
271 return output_type(uninitialized, input.symmetry(), input.domain(), input.codomain(), std::move(keys),
272 input.allocation_context());
273 else
274 return output_type(uninitialized, input.symmetry(), input.domain(), input.codomain(), std::move(keys));
275 }
276 }();
277 using value_type = block_tensor_value_t<Input>;
278 execute_materialization_batch(
279 typename OutputStorage::block_execution_policy{}, output.stored_block_count(), [&](std::size_t output_ordinal) {
280 auto const& key = output.stored_keys()[output_ordinal];
281 auto const found = std::ranges::lower_bound(input.stored_keys(), key);
282 auto output_block = output.block_by_ordinal(output_ordinal);
283 if (found == input.stored_keys().end() || *found != key)
284 {
285 uni20::fill(output_block, value_type{});
286 return;
287 }
288 auto const input_ordinal = static_cast<std::size_t>(found - input.stored_keys().begin());
289 auto input_block = input.block_by_ordinal(input_ordinal);
290 uni20::copy(output_block, input_block);
291 });
292 return output;
293}
294
299template <BlockTensorStorage CenterStorage, BlockTensorView Left, BlockTensorView Right>
300[[nodiscard]] auto make_two_site_center(Left const& left, Right const& right)
301{
302 if constexpr (CompleteBlockStorage<CenterStorage>)
303 {
304 return contract_adjacent<1, CenterStorage>(left, right);
305 }
306 else
307 {
308 auto contracted = contract_adjacent<1, CenterStorage>(left, right);
309 return materialize_local_block_tensor<CenterStorage, true>(contracted);
310 }
311}
312
316template <class CenterStorage>
317using DmrgEnvironmentStorage =
318 std::conditional_t<std::same_as<typename CenterStorage::block_execution_policy, SchedulerBatchBlockExecution>,
319 ParallelPackedSparseBlockStorage<typename CenterStorage::leaf_storage_policy>,
320 PackedSparseBlockStorage<typename CenterStorage::leaf_storage_policy>>;
321
328template <class CenterStorage, BlockTensorView Environment>
329[[nodiscard]] auto place_environment_for_center(Environment const& environment)
330{
331 using environment_storage = typename block_tensor_type_t<Environment>::storage_policy;
332 if constexpr (std::same_as<typename CenterStorage::leaf_storage_policy,
333 typename environment_storage::leaf_storage_policy>)
334 {
336 }
337 else
338 {
339 return materialize_local_block_tensor<DmrgEnvironmentStorage<CenterStorage>, false>(environment);
340 }
341}
342
343inline void validate_two_site_dmrg_direction(MpsSweepDirection direction)
344{
346 throw std::invalid_argument("two-site DMRG received an invalid sweep direction");
347}
348
349template <uni20::Real Real> void validate_two_site_dmrg_options(TwoSiteDmrgOptions<Real> const& options)
350{
351 if (options.local_solver.matvec_iterations == 0)
352 throw std::invalid_argument("two-site DMRG requires at least one local matvec iteration");
353}
354
355template <uni20::Real Real> void validate_two_site_dmrg_run_options(TwoSiteDmrgRunOptions<Real> const& options)
356{
357 validate_two_site_dmrg_direction(options.initial_direction);
358 validate_two_site_dmrg_options(options.bond_options);
359 if (options.maximum_sweeps == 0) throw std::invalid_argument("two-site DMRG run requires at least one sweep");
360 if (!uni20::isfinite(options.energy_tolerance) || options.energy_tolerance < Real{})
361 throw std::invalid_argument("two-site DMRG energy tolerance must be finite and nonnegative");
362}
363
364inline auto opposite_dmrg_direction(MpsSweepDirection direction) -> MpsSweepDirection
365{
368}
369
370template <uni20::Real Real> auto dmrg_abs(Real value) -> Real
371{
372 using std::abs;
373 return abs(value);
374}
375
376template <uni20::Real Real> auto terminal_energies_converged(Real previous, Real current, Real tolerance) -> bool
377{
378 Real const effective_tolerance = tolerance > Real{} ? tolerance : Real{100} * uni20::numeric_limits<Real>::epsilon();
379 Real const scale = std::max({Real{1}, dmrg_abs(previous), dmrg_abs(current)});
380 return dmrg_abs(current - previous) <= effective_tolerance * scale;
381}
382
383template <class Ops, class Measurements> class MeasuredDmrgKrylovOps {
384 public:
385 using ops_type = std::remove_cvref_t<Ops>;
386 using tensor_type = typename ops_type::tensor_type;
387 using scalar_type = typename ops_type::scalar_type;
388 using real_type = typename ops_type::real_type;
389
390 MeasuredDmrgKrylovOps(ops_type ops, Measurements& measurements) : ops_(std::move(ops)), measurements_(measurements)
391 {}
392
393 [[nodiscard]] auto problem_dimension() const noexcept -> std::size_t { return ops_.problem_dimension(); }
394
395 [[nodiscard]] auto vector_dimension(tensor_type const& vector) const -> std::size_t
396 {
397 return ops_.vector_dimension(vector);
398 }
399
400 [[nodiscard]] auto allocate_like(tensor_type const& vector) const -> tensor_type
401 {
402 return this->measure_detailed(TwoSiteDmrgPerformanceEvent::krylov_vector_allocation,
403 [&] { return ops_.allocate_like(vector); });
404 }
405
406 void copy(tensor_type& output, tensor_type const& input) const
407 {
408 this->measure_detailed(TwoSiteDmrgPerformanceEvent::krylov_vector_update, [&] { ops_.copy(output, input); });
409 }
410
411 void axpy(tensor_type& output, scalar_type factor, tensor_type const& input) const
412 {
414 [&] { ops_.axpy(output, factor, input); });
415 }
416
417 void scal(tensor_type& vector, scalar_type factor) const
418 {
419 this->measure_detailed(TwoSiteDmrgPerformanceEvent::krylov_vector_update, [&] { ops_.scal(vector, factor); });
420 }
421
422 void set_zero(tensor_type& vector) const
423 {
424 this->measure_detailed(TwoSiteDmrgPerformanceEvent::krylov_vector_update, [&] { ops_.set_zero(vector); });
425 }
426
427 [[nodiscard]] auto inner_product(tensor_type const& lhs, tensor_type const& rhs) const -> scalar_type
428 {
429 return this->measure_detailed(TwoSiteDmrgPerformanceEvent::krylov_reduction,
430 [&] { return ops_.inner_product(lhs, rhs); });
431 }
432
433 [[nodiscard]] auto norm(tensor_type const& vector) const -> real_type
434 {
435 return this->measure_detailed(TwoSiteDmrgPerformanceEvent::krylov_reduction, [&] { return ops_.norm(vector); });
436 }
437
438 void matvec(tensor_type& output, tensor_type const& input)
439 {
441 [&] { ops_.matvec(output, input); });
442 }
443
444 private:
445 template <class Function>
446 decltype(auto) measure_detailed(TwoSiteDmrgPerformanceEvent event, Function&& function) const
447 {
448 if constexpr (performance::measurement_level_v<Measurements> == performance::MeasurementLevel::detailed)
449 return performance::measure_duration(measurements_, event, std::forward<Function>(function));
450 else
451 return std::invoke(std::forward<Function>(function));
452 }
453
454 ops_type ops_;
455 Measurements& measurements_;
456};
457
458template <class Center, class EffectiveHamiltonian, uni20::Real Real, class Measurements>
459 requires performance::DurationMeasurementPolicy<Measurements, TwoSiteDmrgPerformanceEvent>
460auto solve_two_site_ground_state(Center const& initial, EffectiveHamiltonian effective_hamiltonian,
461 DmrgLanczosOptions<Real> const& options, Measurements& measurements)
462{
463 using scalar_type = block_tensor_value_t<Center>;
464 auto solve = [&](auto& ops) { return dmrg_lanczos_ground_state<scalar_type>(ops, initial, options); };
465
466 krylov::BlockTensorMatrixFreeOps ops(initial, std::move(effective_hamiltonian));
467 if constexpr (performance::measurement_level_v<Measurements> == performance::MeasurementLevel::none)
468 {
469 return solve(ops);
470 }
471 else
472 {
473 MeasuredDmrgKrylovOps<decltype(ops), Measurements> measured_ops(std::move(ops), measurements);
474 return solve(measured_ops);
475 }
476}
477
478} // namespace detail
479
502template <class MpsChain, class MpoChain, SparseBlockStorage EnvironmentStorage, class Measurements,
503 BlockTensorStorage CenterStorage = typename MpsChain::storage_policy>
504 requires detail::TwoSiteCenterStorageFor<CenterStorage, typename MpsChain::value_type> &&
505 performance::DurationMeasurementPolicy<Measurements, TwoSiteDmrgPerformanceEvent>
506[[nodiscard]] auto
507optimize_two_site_dmrg_bond(MpsChain& mps, MpoChain const& mpo,
509 MpsSweepDirection direction,
511 Measurements& measurements, CenterStorage center_storage = {})
512{
513 using scalar_type = typename MpsChain::value_type;
514 using real_type = make_real_t<scalar_type>;
516 "two-site DMRG requires a real or complex scalar with LAPACK support");
517
518 detail::validate_two_site_dmrg_direction(direction);
519 detail::validate_two_site_dmrg_options(options);
520 if (!cache.is_attached_to(mps, mpo))
521 throw std::invalid_argument("two-site DMRG cache is attached to different chain objects");
522 if (first_site >= mps.size() || first_site + 1 >= mps.size())
523 throw std::out_of_range("two-site DMRG pair index is out of range");
524
526 static_cast<void>(center_storage);
528 return detail::make_two_site_center<CenterStorage>(mps.site(first_site), mps.site(first_site + 1));
529 });
530 auto local_solution =
532 auto const& left_environment = cache.left_environment(first_site);
533 auto const& right_environment = cache.right_environment(first_site + 2);
534 auto placed_left = detail::place_environment_for_center<CenterStorage>(left_environment);
535 auto placed_right = detail::place_environment_for_center<CenterStorage>(right_environment);
536 auto effective_hamiltonian =
537 TwoSiteEffectiveHamiltonian(initial, std::move(placed_left), as_block_tensor_view(mpo.site(first_site)),
538 as_block_tensor_view(mpo.site(first_site + 1)), std::move(placed_right));
539 return detail::solve_two_site_ground_state(initial, std::move(effective_hamiltonian), options.local_solver,
540 measurements);
541 });
542
543 real_type const local_energy = local_solution.energy;
544 real_type const residual_bound = local_solution.residual_bound;
545 int const iteration_count = local_solution.iteration_count;
546 int const matvec_count = local_solution.matvec_count;
547 auto decomposition = performance::measure_duration(measurements, TwoSiteDmrgPerformanceEvent::block_svd, [&] {
548 return decompose_two_site_center(local_solution.vector, {}, measurements,
550 });
552 return select_svd_states(decomposition.spectrum(), options.truncation);
553 });
554 auto installed =
556 return replace_two_site_from_svd(mps, first_site, decomposition, selection, direction,
557 {.bond_label = mps.site(first_site).codomain().template space<0>().label()});
558 });
559
561 if (direction == MpsSweepDirection::left_to_right)
562 static_cast<void>(cache.left_environment(first_site + 1));
563 else
564 static_cast<void>(cache.right_environment(first_site + 1));
565 });
566
567 return TwoSiteDmrgStepResult<real_type, decltype(installed)>{.first_site = first_site,
568 .direction = direction,
569 .local_energy = local_energy,
570 .residual_bound = residual_bound,
571 .iteration_count = iteration_count,
572 .matvec_count = matvec_count,
573 .bond = std::move(installed)};
574 });
575}
576
578template <class MpsChain, class MpoChain, SparseBlockStorage EnvironmentStorage,
579 BlockTensorStorage CenterStorage = typename MpsChain::storage_policy>
580 requires detail::TwoSiteCenterStorageFor<CenterStorage, typename MpsChain::value_type>
581[[nodiscard]] auto
582optimize_two_site_dmrg_bond(MpsChain& mps, MpoChain const& mpo,
584 MpsSweepDirection direction,
586 CenterStorage center_storage = {})
587{
588 performance::NoMeasurements measurements;
589 return optimize_two_site_dmrg_bond(mps, mpo, cache, first_site, direction, options, measurements, center_storage);
590}
591
610template <class MpsChain, class MpoChain, SparseBlockStorage EnvironmentStorage, class Measurements,
611 BlockTensorStorage CenterStorage = typename MpsChain::storage_policy>
612 requires detail::TwoSiteCenterStorageFor<CenterStorage, typename MpsChain::value_type> &&
613 performance::DurationMeasurementPolicy<Measurements, TwoSiteDmrgPerformanceEvent>
614[[nodiscard]] auto sweep_two_site_dmrg(MpsChain& mps, MpoChain const& mpo,
616 MpsSweepDirection direction,
618 Measurements& measurements, CenterStorage center_storage = {})
619{
620 detail::validate_two_site_dmrg_direction(direction);
621 if (mps.size() < 2) throw std::invalid_argument("two-site DMRG sweep requires at least two sites");
622
624 using result_type = decltype(optimize_two_site_dmrg_bond(mps, mpo, cache, std::size_t{}, direction, options,
625 measurements, center_storage));
626 std::vector<result_type> result;
627 result.reserve(mps.size() - 1);
628 if (direction == MpsSweepDirection::left_to_right)
629 {
630 for (std::size_t first_site = 0; first_site + 1 < mps.size(); ++first_site)
631 result.push_back(
632 optimize_two_site_dmrg_bond(mps, mpo, cache, first_site, direction, options, measurements, center_storage));
633 }
634 else
635 {
636 for (std::size_t second_site = mps.size() - 1; second_site > 0; --second_site)
637 result.push_back(optimize_two_site_dmrg_bond(mps, mpo, cache, second_site - 1, direction, options, measurements,
638 center_storage));
639 }
640 return result;
641 });
642}
643
645template <class MpsChain, class MpoChain, SparseBlockStorage EnvironmentStorage,
646 BlockTensorStorage CenterStorage = typename MpsChain::storage_policy>
647 requires detail::TwoSiteCenterStorageFor<CenterStorage, typename MpsChain::value_type>
648[[nodiscard]] auto
649sweep_two_site_dmrg(MpsChain& mps, MpoChain const& mpo,
652 CenterStorage center_storage = {})
653{
654 performance::NoMeasurements measurements;
655 return sweep_two_site_dmrg(mps, mpo, cache, direction, options, measurements, center_storage);
656}
657
678template <class MpsChain, class MpoChain, SparseBlockStorage EnvironmentStorage, class Measurements,
679 BlockTensorStorage CenterStorage = typename MpsChain::storage_policy>
680 requires detail::TwoSiteCenterStorageFor<CenterStorage, typename MpsChain::value_type> &&
681 performance::DurationMeasurementPolicy<Measurements, TwoSiteDmrgPerformanceEvent>
682[[nodiscard]] auto run_two_site_dmrg(MpsChain& mps, MpoChain const& mpo,
685 Measurements& measurements, CenterStorage center_storage = {})
686{
688 detail::validate_two_site_dmrg_run_options(options);
689 if (!cache.is_attached_to(mps, mpo))
690 throw std::invalid_argument("two-site DMRG cache is attached to different chain objects");
691 if (mps.size() < 2) throw std::invalid_argument("two-site DMRG run requires at least two sites");
692
694 TwoSiteDmrgRunResult<real_type> result{.sweeps = {}, .converged = false};
695 result.sweeps.reserve(options.maximum_sweeps);
696 std::optional<real_type> previous_terminal_energy;
697 MpsSweepDirection direction = options.initial_direction;
698 for (std::size_t sweep_index = 0; sweep_index < options.maximum_sweeps; ++sweep_index)
699 {
700 auto steps = sweep_two_site_dmrg(mps, mpo, cache, direction, options.bond_options, measurements, center_storage);
701 auto const& terminal = steps.back();
702 real_type maximum_discarded_weight{};
703 std::size_t maximum_bond_dimension = 0;
704 real_type maximum_residual_bound{};
705 int total_iteration_count = 0;
706 int total_matvec_count = 0;
707 for (auto const& step : steps)
708 {
709 maximum_discarded_weight = std::max(maximum_discarded_weight, step.bond.truncation.discarded_weight);
710 maximum_bond_dimension = std::max(maximum_bond_dimension, step.bond.truncation.retained_rank);
711 maximum_residual_bound = std::max(maximum_residual_bound, step.residual_bound);
712 total_iteration_count += step.iteration_count;
713 total_matvec_count += step.matvec_count;
714 }
715
716 real_type const terminal_discarded_weight = terminal.bond.truncation.discarded_weight;
717 bool const terminal_energy_is_global = terminal_discarded_weight == real_type{};
718 std::optional<real_type> energy_change;
719 bool converged = false;
720 if (terminal_energy_is_global)
721 {
722 if (previous_terminal_energy)
723 {
724 energy_change = detail::dmrg_abs(terminal.local_energy - *previous_terminal_energy);
725 converged = detail::terminal_energies_converged(*previous_terminal_energy, terminal.local_energy,
726 options.energy_tolerance);
727 }
728 previous_terminal_energy = terminal.local_energy;
729 }
730 else
731 {
732 previous_terminal_energy.reset();
733 }
734
735 result.sweeps.push_back({.sweep_index = sweep_index,
736 .direction = direction,
737 .terminal_local_energy = terminal.local_energy,
738 .terminal_discarded_weight = terminal_discarded_weight,
739 .terminal_energy_is_global = terminal_energy_is_global,
740 .energy_change = energy_change,
741 .maximum_discarded_weight = maximum_discarded_weight,
742 .maximum_bond_dimension = maximum_bond_dimension,
743 .maximum_residual_bound = maximum_residual_bound,
744 .total_iteration_count = total_iteration_count,
745 .total_matvec_count = total_matvec_count,
746 .converged = converged});
747 if (converged)
748 {
749 result.converged = true;
750 break;
751 }
752 direction = detail::opposite_dmrg_direction(direction);
753 }
754 return result;
755 });
756}
757
759template <class MpsChain, class MpoChain, SparseBlockStorage EnvironmentStorage,
760 BlockTensorStorage CenterStorage = typename MpsChain::storage_policy>
761 requires detail::TwoSiteCenterStorageFor<CenterStorage, typename MpsChain::value_type>
762[[nodiscard]] auto
763run_two_site_dmrg(MpsChain& mps, MpoChain const& mpo,
766 CenterStorage center_storage = {})
767{
768 performance::NoMeasurements measurements;
769 return run_two_site_dmrg(mps, mpo, cache, options, measurements, center_storage);
770}
771
772} // namespace uni20::tensor_network
Defines local pairwise BlockTensor contraction.
Adapts one fixed BlockTensor structure to the Krylov vector interface.
Fixed-size detailed collector retaining every measured batch.
Definition performance_measurements.hpp:157
Fixed-size coarse wall-duration collector indexed by an event enum.
Definition performance_measurements.hpp:76
Directional MPO environment cache borrowed from finite MPS and MPO owners.
Definition environment_cache.hpp:35
auto is_attached_to(mps_type const &mps, mpo_type const &mpo) const noexcept -> bool
Return whether this cache observes the supplied chain objects.
Definition environment_cache.hpp:112
auto left_environment(std::size_t bond) -> environment_type const &
Build and return the left environment at one bond.
Definition environment_cache.hpp:144
auto right_environment(std::size_t bond) -> environment_type const &
Build and return the right environment at one bond.
Definition environment_cache.hpp:169
Local BlockTensor storage with one independently scheduled async value per block.
Definition block_tensor_storage.hpp:142
BlockTensor storage whose stored numerical blocks are generalized diagonals.
Definition block_tensor_storage.hpp:71
Concept for real or complex scalar fields with real LAPACK coverage.
Definition scalar_concepts.hpp:133
BlockTensor storage whose blocks reside within one local process.
Definition block_tensor_storage.hpp:118
Concept for real scalar types (float, double, etc.).
Definition scalar_concepts.hpp:69
locale_t value
Definition data_table.cpp:49
Coroutine scheduler for AsyncTask.
Defines the lightweight fixed-step Lanczos solve used by finite DMRG.
Builds and invalidates finite-chain MPO environments.
Async< double > solve(double InitialValue)
Definition gradient_solver.cpp:21
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
Scalar math helper utilities.
Definition qnum.hpp:403
Definition terminal.cpp:32
void execute_batch(std::size_t size, Function &&function)
Execute a synchronous lightweight batch on the global scheduler.
Definition debug_scheduler.hpp:245
void scal(Scalar const &alpha, std::span< Scalar > vector)
Scale a local dense vector in place.
Definition dense_linalg.hpp:193
void axpy(std::span< Scalar > y, Scalar const &alpha, std::span< Scalar const > x)
Add a scaled local dense vector to another vector.
Definition dense_linalg.hpp:206
void copy(std::span< Scalar > destination, std::span< Scalar const > source)
Copy a local dense vector.
Definition dense_linalg.hpp:183
decltype(auto) measure_duration(Measurements &measurements, Event event, Function &&function)
Invoke a function with compile-time-gated wall-duration measurement.
Definition performance_measurements.hpp:251
typename optional_traits< T >::value_type value_type
Definition data_table.hpp:42
Definition right_first_rabc.hpp:34
auto sweep_two_site_dmrg(MpsChain &mps, MpoChain const &mpo, MpoEnvironmentCache< MpsChain, MpoChain, EnvironmentStorage > &cache, MpsSweepDirection direction, TwoSiteDmrgOptions< make_real_t< typename MpsChain::value_type > > const &options, Measurements &measurements, CenterStorage center_storage={})
Traverse every adjacent bond once in one measured two-site DMRG direction.
Definition two_site_dmrg.hpp:614
auto replace_two_site_from_svd(FiniteMps< Scalar, Bond, Physical, SiteStorage > &mps, std::size_t first_index, Decomposition const &decomposition, BlockSvdSelection< typename Decomposition::real_type > const &selection, MpsSweepDirection direction, BlockSvdMaterializationOptions options={})
Materialize and install a selected two-site split in a finite MPS.
Definition two_site_split.hpp:224
auto optimize_two_site_dmrg_bond(MpsChain &mps, MpoChain const &mpo, MpoEnvironmentCache< MpsChain, MpoChain, EnvironmentStorage > &cache, std::size_t first_site, MpsSweepDirection direction, TwoSiteDmrgOptions< make_real_t< typename MpsChain::value_type > > const &options, Measurements &measurements, CenterStorage center_storage={})
Optimize and replace one adjacent MPS pair with a measured ground-state DMRG step.
Definition two_site_dmrg.hpp:507
MpsSweepDirection
Direction in which a two-site split moves the MPS canonical center.
Definition two_site_split.hpp:28
@ left_to_right
Absorb singular values into the right site.
@ right_to_left
Absorb singular values into the left site.
constexpr auto two_site_dmrg_performance_event_name(TwoSiteDmrgPerformanceEvent event) noexcept -> std::string_view
Return the stable display name of one DMRG performance event.
Definition two_site_dmrg.hpp:102
auto run_two_site_dmrg(MpsChain &mps, MpoChain const &mpo, MpoEnvironmentCache< MpsChain, MpoChain, EnvironmentStorage > &cache, TwoSiteDmrgRunOptions< make_real_t< typename MpsChain::value_type > > const &options, Measurements &measurements, CenterStorage center_storage={})
Run measured alternating directional sweeps until terminal-energy convergence.
Definition two_site_dmrg.hpp:682
TwoSiteDmrgPerformanceEvent
Stable phase identifiers for two-site DMRG performance measurements.
Definition two_site_dmrg.hpp:69
auto decompose_two_site_center(Center const &center, linalg::SvdOptions options, Measurements &measurements, Event batch_event)
Factorize a canonical two-site MPS center by its internal cut with performance measurements.
Definition two_site_split.hpp:138
constexpr uninitialized_t uninitialized
Explicit allocation tag for overwrite outputs and scratch space.
Definition common/initialization.hpp:22
constexpr auto abs(basic_half_int< T > value) -> basic_half_int< T >
Return the absolute value of a half-integer.
Definition half_int.hpp:431
void inner_product(BackendSelector selector, async::Async< OutputTensor > &output, async::Async< LhsTensor > const &lhs, async::Async< RhsTensor > const &rhs)
Schedule an inner product into an explicit async scalar Tensor.
Definition linalg/async/reductions.hpp:455
auto select_svd_states(std::span< BlockSvdState< Real > const > spectrum, linalg::SvdTruncationPolicy< Real > const &policy={}) -> BlockSvdSelection< Real >
Apply the standard truncation policy to a globally sorted block-SVD spectrum.
Definition block_tensor_svd.hpp:1086
mpreal norm(mpcomplex const &z)
Definition mpcomplex.hpp:494
void fill(BackendSelector selector, async::Async< OutputTensor > &output, Value &&value)
Fill an existing async Tensor without reading its old values.
Definition linalg/async/transform.hpp:205
void scale(Tensor &tensor, Scalar factor)
Multiply every stored numerical block by a scalar in place.
Definition block_tensor_linear.hpp:400
void copy(BackendSelector selector, async::Async< OutputTensor > &output, async::Async< InputTensor > const &input)
Schedule a Tensor copy through an explicit backend selector.
Definition linalg/async/copy.hpp:174
auto as_block_tensor_view(Tensor &tensor)
Materialize a borrowed identity view over an existing BlockTensor view.
Definition block_tensor_permute.hpp:186
void set_zero(Tensor &tensor)
Set every stored numerical block to zero without changing structure.
Definition block_tensor_linear.hpp:369
Compile-time-gated performance duration measurements.
Execute independent block-level work through the active scheduler's synchronous batch interface.
Definition block_tensor_storage.hpp:41
Execute block-level work serially on the calling thread.
Definition block_tensor_storage.hpp:37
Rank-selection policy for a truncated singular value decomposition.
Definition ops/truncated_svd.hpp:34
std::size_t minimum_retained_extent
Definition ops/truncated_svd.hpp:35
Project-level numeric limits customization point.
Definition numeric_limits.hpp:16
Trait to extract the scalar type from a type T.
Definition scalar_traits.hpp:93
Numerical policy for one lightweight DMRG local Lanczos solve.
Definition dmrg_lanczos.hpp:32
Numerical policies for one finite-chain two-site DMRG update.
Definition two_site_dmrg.hpp:42
linalg::SvdTruncationPolicy< Real > truncation
Global block-SVD state-selection policy for each updated bond.
Definition two_site_dmrg.hpp:46
DmrgLanczosOptions< Real > local_solver
Fixed-work Lanczos policy for each local solve.
Definition two_site_dmrg.hpp:44
Policies for an alternating finite-chain two-site DMRG run.
Definition two_site_dmrg.hpp:56
Real energy_tolerance
Relative/absolute hybrid tolerance for consecutive terminal energies.
Definition two_site_dmrg.hpp:62
std::size_t maximum_sweeps
Maximum number of alternating directional traversals.
Definition two_site_dmrg.hpp:60
TwoSiteDmrgOptions< Real > bond_options
Local solve and bond-truncation policy shared by every update.
Definition two_site_dmrg.hpp:58
MpsSweepDirection initial_direction
Direction of the first traversal.
Definition two_site_dmrg.hpp:64
Result of an alternating finite-chain two-site DMRG run.
Definition two_site_dmrg.hpp:174
std::vector< TwoSiteDmrgSweepSummary< Real > > sweeps
Per-sweep summaries in execution order.
Definition two_site_dmrg.hpp:176
bool converged
Whether the final executed sweep satisfied the energy criterion.
Definition two_site_dmrg.hpp:178
Diagnostics and selected bond data from one DMRG bond update.
Definition two_site_dmrg.hpp:185
MpsSweepDirection direction
Direction in which the canonical center moved.
Definition two_site_dmrg.hpp:189
int matvec_count
Number of effective-Hamiltonian applications.
Definition two_site_dmrg.hpp:197
Real local_energy
Lowest local Ritz value before SVD truncation.
Definition two_site_dmrg.hpp:191
int iteration_count
Number of Lanczos projection steps.
Definition two_site_dmrg.hpp:195
std::size_t first_site
Index of the left site in the optimized pair.
Definition two_site_dmrg.hpp:187
InstalledBond bond
Selected Schmidt spectrum and truncation diagnostics.
Definition two_site_dmrg.hpp:199
Real residual_bound
Residual bound reported for the installed Ritz vector.
Definition two_site_dmrg.hpp:193
Aggregate diagnostics for one completed directional DMRG sweep.
Definition two_site_dmrg.hpp:144
Real terminal_discarded_weight
Terminal-bond normalized discarded squared norm.
Definition two_site_dmrg.hpp:152
int total_iteration_count
Sum of local Lanczos projection steps.
Definition two_site_dmrg.hpp:164
Real maximum_residual_bound
Largest local Ritz residual bound over the sweep.
Definition two_site_dmrg.hpp:162
Real maximum_discarded_weight
Largest normalized discarded weight over the sweep.
Definition two_site_dmrg.hpp:158
std::size_t sweep_index
Zero-based directional sweep index.
Definition two_site_dmrg.hpp:146
bool terminal_energy_is_global
Whether the terminal local energy is also the installed global-state energy.
Definition two_site_dmrg.hpp:154
int total_matvec_count
Sum of effective-Hamiltonian applications.
Definition two_site_dmrg.hpp:166
std::optional< Real > energy_change
Absolute change from the preceding valid terminal energy.
Definition two_site_dmrg.hpp:156
bool converged
Whether this sweep satisfied the run convergence test.
Definition two_site_dmrg.hpp:168
std::size_t maximum_bond_dimension
Largest retained internal-bond dimension over the sweep.
Definition two_site_dmrg.hpp:160
MpsSweepDirection direction
Direction visited by this sweep.
Definition two_site_dmrg.hpp:148
Real terminal_local_energy
Local Ritz value from the terminal bond before its SVD.
Definition two_site_dmrg.hpp:150
Defines two-site effective-Hamiltonian apply objects.
Splits a two-site center and installs directional MPS factors.