Repository navigation
Conversation
save_density took the width of the name column of density.dat from onesite_operator_names[0]. With no one-site observable the vector is empty, and a ground-state calculation died of a segmentation fault after everything else had been measured and saved. A std.toml with bond Hamiltonians only and no [observable] section is enough: tenes_std then writes no [[observable.onesite]]. The names of all operators are padded to one width in the constructor, so the width is taken from the first kind of operator that has any, and is that of "Energy" when there is none. quasi1d_ctm and onesite_rdm_output carried a one-site observable they did not use, with a comment that said why. They run without it now. observable_density is a new end-to-end test for what density.dat reports; its first case is this one. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
measure_onesite fills the sites on which an observable is not defined with NaN, which is how save_onesite knows to skip them. save_density summed over all sites. A one-site observable given on a part of the sites was reported as nan in density.dat, and when the site Hamiltonian itself was such an observable -- a unit cell that mixes kinds of sites, with a term on one kind only -- Energy was nan too, although every value in onesite_obs.dat and twosite_obs.dat was right. The sites are told apart by site_ops_indices rather than by isnan, so that a NaN that comes out of a measurement still shows. The sum is divided by the number of all sites, not of the sites that have the operator: that is what the two-site observables already are, and it is what makes Energy the energy per site. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The measurement stored the value of an operator by assignment, keyed by the group and the site or the bond, so of several operators of one group on one bond only the last was reported, without a message. tenes_std writes every [[hamiltonian]] as an observable of group 0. A Hamiltonian written as a sum of terms on one bond -- the Ising and the XY part, or Heisenberg and Dzyaloshinskii-Moriya -- was evolved as given, and its Energy missed all the terms but the last. The same went for two terms on one site, which the report that prompted this did not mention: a field written as 0.25 h and 0.75 h gave three quarters of the site energy. They are summed now, for one-site, two-site and multi-site observables. What cannot be summed is a reference. ops of a two-site or multi-site observable, and a correlation function, name the one-site operator of a group on a site, and site_ops_indices keeps one index for it. With several operators there the last one would be used, which is the silent choice this commit removes elsewhere, so the constructor rejects the input. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
measure_twosite and measure_multisite contract a window of at most 4 x 4 sites. An operator that did not fit was left out with a warning on stderr when the measurement came to it, and the run finished normally. The simple update has no such limit: tenes_std carries a longer bond through a chain of nearest-neighbour gates. So a Hamiltonian with a bond of four lattice spacings was evolved in full and reported an Energy that missed the bond. It was met with a kagome cell laid out on the square lattice, where 4 of 24 bonds were lost. The fermion mode already refuses such an observable, when the input is read and again at the measurement, and tenes_std refuses the Hamiltonian bond. This does the same for bosons, in the same two places: validate_measure_window() is called after the fermion checks in main.cpp, so that a calculation does not start, and by measure(), measure_density(), measure_twosite() and measure_multisite(), for a state that was not made from an input file. The warnings are gone. It is not in the constructor: the fermion tests build a state with such an observable to see the measurement refuse it. tenes_std rejects the observable too, after its fermion checks, because it is where the observable is made from the Hamiltonian and where it can say so. A bond out of the window is still accepted and evolved when the input gives an energy observable of its own in place of the automatic one. test_bosonic_bond_outside_the_window_is_accepted pinned the former behaviour for both cases; it is now two tests, one for each. None of the inputs under sample/ and test/data has such an observable. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
yomichi
left a comment
There was a problem hiding this comment.
Thanks for this. I checked the four fixes, and they behave as described. Below are a few requests, mainly about the tests and the documentation.
1. terms_on_the_same_site_and_bond cannot tell a sum from "the first term only" on the bond.
In the fully polarized state = 0, so with the bond split into ISING + XY, both a correct sum and an implementation that keeps only the first term give -0.25. I replaced the += in twosite_obs.cpp with emplace (first term wins) and all five cases still passed. The test also passes on develop if the two terms are given in the other order. Could you split the bond into two terms whose values are both nonzero, as is done for the field with field(0.25) + field(0.75)?
2. (Optional) Multisite and fermion sums are not covered.
The += in multisite_obs.cpp and in the parity branches of the fermion mode (add_local_obs) are not reached by any test. A multisite case in observable_density would cover the first one cheaply.
3. standard_format.rst: "a bond out of this range is an error" is too strong.
As the PR description says, and as test_bosonic_bond_outside_the_window_is_evolved pins, tenes_std accepts such a bond when the input gives its own group-0 two-site observable. Could the sentence say that the bond is an error when it is measured as the automatic bond_hamiltonian?
4. output_format.rst: "divided by the number of all the sites in the unit cell".
save_density counts only the sites with physical_dims > 1, and simple_format.rst says "per non-vacancy site" for the kagome lattice. Could this say "the number of sites in the unit cell, not counting vacancies"? Same for the Japanese version.
5. (Optional) Nothing pins that the check runs at read time.
If I remove validate_measure_window() from main.cpp, observable_out_of_range still passes, because measure() raises the same error, only after the whole calculation. The check of multisite observables in C++ is not covered either; only the one in tenes_std is. A case that checks that no output/ files are written (or that the run fails before the simple update) would pin the first.
Not tested: an MPI build.
Review of #120. The bond term was split into its Ising part and its XY part. In the polarized state the XY part is zero, so the sum equals the Ising part alone: the case passed with "the first term wins" in place of the sum, and on develop with the two terms in the other order. The bond is now a quarter and three quarters of the Heisenberg term, as the field already was. The sum of multi-site observables was not reached by any test. multisite_terms_on_the_same_sites gives S^z S^z S^z as a quarter and three quarters. Nothing pinned that an observable out of the window is refused when the input is read: with the check removed from main.cpp, measure() raises the same error after the whole calculation and the case passed. tenes makes the output directory after reading the input and before anything else, so the cases now require that it is not there. multisite_observable_out_of_range does the same for the multi-site check of tenes, which only tenes_std's own check covered. Each of these fails when the code is broken accordingly: the first term wins or the last term wins in twosite_obs.cpp, the last term wins in multisite_obs.cpp, and no check in main.cpp. The sums in the parity branches of the fermion mode are still not covered. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Review of #120. standard_format.rst said that a Hamiltonian bond out of the measurement window is an error. It is one when the bond is measured as the automatic bond_hamiltonian. With an observable of group 0 given in observable.twosite, which replaces the automatic one, tenes_std accepts the bond and evolves with it, as the description of the pull request says and test_bosonic_bond_outside_the_window_is_evolved pins. output_format.rst and NEWS said that a density is divided by the number of all sites of the unit cell. save_density counts the sites with a physical dimension larger than 1, and simple_format.rst already says so: vacancies are not counted. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
|
Thank you for the careful review. All five points are addressed in 5843479 (tests) and 67b87cf (documentation).
Each new check fails when the code is broken accordingly: first term wins and last term wins in
|
yomichi
left a comment
There was a problem hiding this comment.
Thanks, all five points are addressed. I checked 67b87cf with mutations: first term wins and last term wins in twosite_obs.cpp, last term wins in multisite_obs.cpp, no check in main.cpp, and no multi-site check in validate_measure_window() each make observable_density fail, and the unmodified code passes. Leaving the fermion parity branches to a later PR is fine.
Summary
Four defects in the measurement made
density.datreport something other than the observables of the input, or nothing at all. None of them printed an error.density.datis writtennan, andEnergy = nanwhen it is the site Hamiltonian|dx| > 3or|dy| > 3(bosons)One commit per defect.
Changes
Write
density.datwhen the input has no one-site observablesave_densitytook the width of the name column fromonesite_operator_names[0]. With no one-site observable the vector is empty, and a ground-state calculation died after everything else had been measured and saved. Astd.tomlwith bond Hamiltonians only and no[observable]section is enough.The width is now taken from the first kind of operator that has any, and is that of
Energywhen there is none.quasi1d_ctmandonesite_rdm_outputcarried a one-site observable they did not use, to avoid this crash. They run without it now.Leave the sites without an operator out of the density
measure_onesitefills the sites on which an observable is not defined with NaN, andsave_densitysummed over all sites. When the site Hamiltonian itself was given on a part of the sites, as in a unit cell that mixes kinds of sites,Energywasnanalthough every value inonesite_obs.datandtwosite_obs.datwas right.site_ops_indices, not byisnan, so a NaN that comes out of a measurement still shows.Energythe energy per site.Add up the observables of one group on the same site or bond
The measurement stored a value by assignment, keyed by the group and the site or bond.
tenes_stdwrites every[[hamiltonian]]as an observable of group 0, so a Hamiltonian written as a sum of terms on one bond (Ising part and XY part, or Heisenberg and Dzyaloshinskii-Moriya) was evolved as given and itsEnergymissed all the terms but the last. The same went for two terms on one site.They are summed now, for one-site, two-site and multi-site observables, including the parity branches of the fermion mode.
A reference cannot be summed.
opsof a two-site or multi-site observable, andcorrelation, name the one-site operator of a group on a site, andsite_ops_indiceskeeps one index for it. An input that refers to a one-site observable given more than once on a site is now rejected.Reject an observable that is too long to be measured
measure_twositeandmeasure_multisitecontract a window of at most 4 x 4 sites. The simple update has no such limit, becausetenes_stdcarries a longer bond through a chain of nearest-neighbour gates. A Hamiltonian with a bond of four lattice spacings was evolved in full and reported anEnergythat missed the bond.The fermion mode already refuses such an observable, when the input is read and again at the measurement, and
tenes_stdrefuses the Hamiltonian bond. This PR does the same for bosons, in the same places.tenes: the newvalidate_measure_window()(src/iTPS/measure_window.hpp) is called after the fermion checks when the input is read, so that a calculation does not start, and again bymeasure(),measure_density(),measure_twosite()andmeasure_multisite(), for a state that was not made from an input file. The warnings are removed.tenes_std: rejects the observable after its fermion checks, and says when it comes from a[[hamiltonian]]bond.The messages of the fermion mode do not change, since its checks run first. The manual already gave this range for
observable.twositeandobservable.multisite. None of the inputs undersample/andtest/data/has such an observable.Behavior changes
|dx| > 3or|dy| > 3, or a multi-site observable that does not fit into 4 x 4 sites, is an input error. It used to be a warning.tenes_std, bosons: a[[hamiltonian]]bond out of the window is rejected when the automaticbond_hamiltonianwould hold it. It is still accepted and evolved when the input gives an energy observable of group 0 of its own, since then nothing out of the window is measured.ops-form observable or a correlation function that refers to a one-site observable given more than once on a site is an input error.density.datof a one-site observable given on a part of the sites is the sum divided by the number of all sites.Note for reviewers: an existing test is changed
test_bosonic_bond_outside_the_window_is_acceptedintest/python/test_fermion_chain.pypinned thattenes_stdaccepts a bosonic bond out of the window, with the user's own energy observable and with the automatic one. The second case is what this PR changes, so the test is now two:test_bosonic_bond_outside_the_window_is_evolved: with the user's own observable, accepted as before.test_bosonic_bond_outside_the_window_cannot_be_the_energy: with the automatic one, rejected.If the acceptance in the second case was intended, the last commit is the one to drop or to turn into a warning from
tenes_std.Documentation
output_format.rst: what the value indensity.datis for an observable on a part of the sites.observable_section.rst: observables of the same group are summed; an observable out of range is an input error.standard_format.rst: terms on the same site or bond are summed; the range of a Hamiltonian bond.NEWS.md.English and Japanese.
Tests
observable_density, an end-to-end test with five cases, one or two per commit. Every case is a ferromagnetic Heisenberg chain whose exact ground state is the fully polarized product state, so every expected value is known in closed form. All five cases fail with a build ofdevelop.test/python/test_tenes_std.pyfor the range check oftenes_std.ctest: 78/78 (Apple clang, no MPI, Release).Not tested:
🤖 Generated with Claude Code