Xped
Loading...
Searching...
No Matches
iPEPSSolverImag.hpp
Go to the documentation of this file.
1#ifndef XPED_IPEPS_SOLVER_IMAG_H_
2#define XPED_IPEPS_SOLVER_IMAG_H_
3
5
8
9namespace Xped {
10
11template <typename Scalar, typename Symmetry>
13{
14 template <typename Sym>
16
17 iPEPSSolverImag() = delete;
18
21 , Psi(Psi_in)
22 , H(H_in)
23 {
24 std::filesystem::create_directories(imag_opts.working_directory / imag_opts.obs_directory);
26 if(not imag_opts.obs_directory.empty()) {
27 std::filesystem::create_directories(imag_opts.working_directory / imag_opts.obs_directory);
28 if(std::filesystem::exists(imag_opts.working_directory / imag_opts.obs_directory /
29 std::filesystem::path(this->H.file_name() + fmt::format("_seed={}_id={}.h5", imag_opts.seed, imag_opts.id)))) {
30 HighFive::File file((imag_opts.working_directory / imag_opts.obs_directory).string() + "/" + this->H.file_name() +
31 fmt::format("_seed={}_id={}.h5", imag_opts.seed, imag_opts.id),
32 imag_opts.resume ? HighFive::File::ReadWrite : HighFive::File::ReadOnly);
33 for(auto iD = 0ul; auto D : imag_opts.Ds) {
34 for(auto chi : imag_opts.chis[iD]) {
35 if(file.exist(fmt::format("/{}/{}", D, chi))) {
36 fmt::print(fg(fmt::color::red),
37 "There already exists data in observable file for D={}, chi={}.\n Filename:{}.\n",
38 D,
39 chi,
40 (imag_opts.working_directory / imag_opts.obs_directory).string() + "/" + this->H.file_name() +
41 fmt::format("_seed={}_id={}.h5", imag_opts.seed, imag_opts.id));
42 std::cout << std::flush;
43 throw;
44 }
45 ++iD;
46 }
47 }
48 } else {
49 try {
50 HighFive::File file((imag_opts.working_directory / imag_opts.obs_directory).string() + "/" + this->H.file_name() +
51 fmt::format("_seed={}_id={}.h5", imag_opts.seed, imag_opts.id),
52 imag_opts.resume ? HighFive::File::ReadWrite : HighFive::File::Excl);
53 } catch(const std::exception& e) {
54 fmt::print(fg(fmt::color::red),
55 "Error while creating the observable file for this simulation:{}.\n",
56 (imag_opts.working_directory / imag_opts.obs_directory).string() + "/" + this->H.file_name() +
57 fmt::format("_seed={}_id={}.h5", imag_opts.seed, imag_opts.id));
58 std::cout << std::flush;
59 throw;
60 }
61 }
62 }
63 }
64
65 void solve()
66 {
68 "{}: Model={}(Bonds: V:{}, H:{}, D1: {}, D2: {})",
69 fmt::styled("iPEPSSolverImag", fmt::emphasis::bold),
70 H.format(),
71 (H.bond & Opts::Bond::V) == Opts::Bond::V,
72 (H.bond & Opts::Bond::H) == Opts::Bond::H,
74 (H.bond & Opts::Bond::D2) == Opts::Bond::D2);
77
78 init_psi();
79
80 std::vector<std::vector<double>> Es(imag_opts.chis.size());
81 for(auto iD = 0ul; iD < Es.size(); ++iD) { Es[iD].resize(imag_opts.chis[iD].size()); }
82 util::Stopwatch<> total_t;
83 std::chrono::seconds evol_time{0}, ctm_time{0};
84 for(auto iD = 0; auto D : imag_opts.Ds) {
85 util::Stopwatch<> evol_t;
86 Psi->D = D;
87 for(std::size_t i = 0; i < imag_opts.t_steps.size(); ++i) {
88 util::Stopwatch<> step_t;
91 double diff = 0.;
92 std::size_t steps = 0ul;
94 for(auto step = 0ul; step < imag_opts.t_steps[i]; ++step) {
95 ++steps;
96 Jim.t_step(*Psi);
97 if(step == 0) {
98 conv_h = Jim.spectrum_h;
99 conv_v = Jim.spectrum_v;
100 } else {
101 TMatrix<double> diff_h(Psi->cell().pattern);
102 TMatrix<double> diff_v(Psi->cell().pattern);
103 for(auto i = 0ul; i < conv_h.size(); ++i) {
104 if(conv_h[i].coupledDomain() != Jim.spectrum_h[i].coupledDomain() or
105 conv_h[i].coupledCodomain() != Jim.spectrum_h[i].coupledCodomain()) {
106 diff_h[i] = std::nan("1");
107 } else {
108 diff_h[i] = (conv_h[i] - Jim.spectrum_h[i]).norm();
109 }
110 if(conv_v[i].coupledDomain() != Jim.spectrum_v[i].coupledDomain() or
111 conv_v[i].coupledCodomain() != Jim.spectrum_v[i].coupledCodomain()) {
112 diff_h[i] = std::nan("1");
113 } else {
114 diff_v[i] = (conv_v[i] - Jim.spectrum_v[i]).norm();
115 }
116 }
117 diff = std::max(*std::max_element(diff_h.begin(), diff_h.end()), *std::max_element(diff_v.begin(), diff_v.end()));
118 if(diff < imag_opts.tol * imag_opts.dts[i] * imag_opts.dts[i] and step > imag_opts.min_steps) { break; }
119 conv_h = Jim.spectrum_h;
120 conv_v = Jim.spectrum_v;
121 }
122 }
124 " ImagSteps(D={}: Nτ={:^4d}, dτ={:.1e}): runtime={}, conv={:2.3g}",
125 D,
126 steps,
127 imag_opts.dts[i],
128 step_t.time_string(),
129 diff);
130 Psi->updateAtensors();
131 constexpr std::size_t flags = yas::file /*IO type*/ | yas::binary; /*IO format*/
132 yas::file_ostream ofs(
133 (imag_opts.working_directory.string() + "/" + H.file_name() + fmt::format("_D={}_id={}.psi", D, imag_opts.id)).c_str(),
134 /*trunc*/ 1);
135 yas::save<flags>(ofs, *Psi);
136 // Psi->info();
137 }
138 Log::per_iteration(imag_opts.verbosity, " {}", Psi->info());
139 evol_time += evol_t.time();
140 util::Stopwatch<> ctm_t;
141 for(auto ichi = 0; auto chi : imag_opts.chis[iD]) {
142 Jack.opts.chi = chi;
143 Es[iD][ichi] = Jack.template solve<double, false>(Psi, nullptr, H);
144
145 if(imag_opts.display_obs or not imag_opts.obs_directory.empty()) { H.computeObs(Jack.getCTM()); }
146 if(imag_opts.display_obs) { Log::per_iteration(imag_opts.verbosity, " Observables:\n{}", H.getObsString(" ")); }
147 if(not imag_opts.obs_directory.empty()) {
148 std::string e_name = fmt::format("/{}/{}/energy", D, chi);
149 HighFive::File file((imag_opts.working_directory / imag_opts.obs_directory).string() + "/" + H.file_name() +
150 fmt::format("_seed={}_id={}.h5", imag_opts.seed, imag_opts.id),
151 HighFive::File::OpenOrCreate);
152 if(not file.exist(e_name)) {
153 HighFive::DataSpace dataspace = HighFive::DataSpace({0, 0}, {HighFive::DataSpace::UNLIMITED, HighFive::DataSpace::UNLIMITED});
154
155 // Use chunking
156 HighFive::DataSetCreateProps props;
157 props.add(HighFive::Chunking(std::vector<hsize_t>{2, 2}));
158
159 // Create the dataset
160 HighFive::DataSet dataset = file.createDataSet(e_name, dataspace, HighFive::create_datatype<double>(), props);
161 }
162 {
163 auto d = file.getDataSet(e_name);
164 std::vector<std::vector<double>> data;
165 data.push_back(std::vector<double>(1, Es[iD][ichi]));
166 std::size_t curr_size = d.getDimensions()[0];
167 d.resize({curr_size + 1, data[0].size()});
168 d.select({curr_size, 0}, {1, data[0].size()}).write(data);
169 }
170 H.obsToFile(file, fmt::format("/{}/{}/", D, chi));
171 }
172 ++ichi;
173 }
174
175 ctm_time += ctm_t.time();
176 ++iD;
177 }
179 "{}(runtime={} [evol={}, ctm={}]) energies:",
180 fmt::styled("iPEPSSolverImag", fmt::emphasis::bold),
181 total_t.time_string(),
182 util::format_secs(evol_time),
183 util::format_secs(ctm_time));
184 for(auto i = 0ul; i < Es.size(); ++i) {
185 for(auto j = 0; j < Es[i].size(); ++j) {
186 Log::on_exit(imag_opts.verbosity, "{:^4}D={:^2d}, χ={:^3d}: E={:.8f}", "↳", imag_opts.Ds[i], imag_opts.chis[i][j], Es[i][j]);
187 }
188 }
189 }
190
191 void init_psi()
192 {
193 if(imag_opts.load != "") {
194 std::filesystem::path load_p(imag_opts.load);
195 if(load_p.is_relative()) { load_p = imag_opts.working_directory / load_p; }
196 switch(imag_opts.load_format) {
197 case Opts::LoadFormat::MATLAB: {
199 "Load initial iPEPS from matlab file {}.\nScale the quantum numbers from matlab by {}.",
202 Psi->loadFromMatlab(load_p, "cpp", imag_opts.qn_scale);
203 break;
204 }
205 case Opts::LoadFormat::NATIVE: {
206 Log::on_entry(imag_opts.verbosity, "Load initial iPEPS from native file {}.", load_p.string());
207 constexpr std::size_t flags = yas::file /*IO type*/ | yas::binary; /*IO format*/
209 try {
210 yas::load<flags>(load_p.string().c_str(), tmp_Psi);
211 } catch(const yas::serialization_exception& se) {
212 fmt::print(
213 "Error while deserializing file ({}) with initial wavefunction.\nThis might be because of incompatible symmetries between this simulation and the loaded wavefunction.",
214 load_p.string());
215 std::cout << std::flush;
216 throw;
217 } catch(const yas::io_exception& ie) {
218 fmt::print("Error while loading file ({}) with initial wavefunction.\n", load_p.string());
219 std::cout << std::flush;
220 throw;
221 } catch(const std::exception& e) {
222 fmt::print("Unknown error while loading file ({}) with initial wavefunction.\n", load_p.string());
223 std::cout << std::flush;
224 throw;
225 }
226 Psi = std::make_shared<iPEPS<Scalar, Symmetry>>(std::move(tmp_Psi));
227 break;
228 }
229 }
230 Psi->initWeightTensors();
231 assert(Psi->cell().pattern == H.data_h.pat);
232 } else {
234 Log::on_entry(imag_opts.verbosity, "Try multiple seeds to find a good random initial state.");
235 Log::on_entry(imag_opts.verbosity, "Used protocol:");
236 Log::on_entry(imag_opts.verbosity, " {:<10} {}", "• seeds:", imag_opts.init_seeds);
237 Log::on_entry(imag_opts.verbosity, " {:<10} {}", "• Ds:", imag_opts.init_Ds);
238 Log::on_entry(imag_opts.verbosity, " {:<10} {}", "• chi:", imag_opts.init_chi);
239 Log::on_entry(imag_opts.verbosity, " {:<10} {}", "• t_steps:", imag_opts.init_t_steps);
240 Log::on_entry(imag_opts.verbosity, " {:<10} {}", "• dts:", imag_opts.init_dts);
241 std::vector<std::shared_ptr<iPEPS<Scalar, Symmetry>>> init_Psis(imag_opts.init_seeds.size());
242 for(auto& init_Psi : init_Psis) { init_Psi = std::make_shared<iPEPS<Scalar, Symmetry>>(*Psi); }
243 std::vector<double> init_Es(imag_opts.init_seeds.size(), 0.);
244 for(auto i = 0ul; i < imag_opts.init_seeds.size(); ++i) {
245 init_Psis[i]->setRandom(imag_opts.init_seeds[i]);
246 init_Psis[i]->initWeightTensors();
247 for(auto D : imag_opts.init_Ds) {
248 init_Psis[i]->D = D;
249 for(std::size_t j = 0; j < imag_opts.init_t_steps.size(); ++j) {
250 util::Stopwatch<> step_t;
252 for(auto step = 0ul; step < imag_opts.init_t_steps[j]; ++step) { Jim.t_step(*init_Psis[i]); }
254 " MultiInit(D={}, seed={}: Nτ={:^4d}, dτ={:.1e}): runtime={}",
255 D,
259 step_t.time_string());
260 }
261 init_Psis[i]->updateAtensors();
262 Log::per_iteration(imag_opts.verbosity, " {}", init_Psis[i]->info());
263 }
265 init_Es[i] = Jack.template solve<double, false>(init_Psis[i], nullptr, H);
266 }
267 std::size_t min_index = std::distance(init_Es.begin(), std::min_element(init_Es.begin(), init_Es.end()));
268 Log::on_entry(imag_opts.verbosity, " Initialization with #{} seeds:", imag_opts.init_seeds.size());
269 for(auto i = 0ul; i < imag_opts.init_seeds.size(); ++i) {
270 Log::on_entry(imag_opts.verbosity, " seed={:<3d} --> energy={:.8f}", imag_opts.init_seeds[i], init_Es[i]);
271 }
272 Log::on_entry(imag_opts.verbosity, " Chose seed={:<3d} with energy={:.8f}", imag_opts.init_seeds[min_index], init_Es[min_index]);
273 Psi = std::move(init_Psis[min_index]);
274 } else {
275 Log::on_entry(imag_opts.verbosity, "Start from random iPEPS with seed={}.", imag_opts.seed);
276 Psi->setRandom(imag_opts.seed);
277 Psi->initWeightTensors();
278 }
279 }
280 }
281
284 std::shared_ptr<iPEPS<Scalar, Symmetry>> Psi;
286};
287
288} // namespace Xped
289
290#endif
Definition: CTMSolver.hpp:18
XPED_CONST CTM< Scalar, Symmetry, TRank, false > & getCTM() XPED_CONST
Definition: CTMSolver.hpp:41
Opts::CTM opts
Definition: CTMSolver.hpp:51
Definition: TimePropagator.hpp:25
void t_step(iPEPS< Scalar, Symmetry > &Psi)
Definition: TimePropagator.cpp:8
TMatrix< Tensor< Scalar, 1, 1, Symmetry > > spectrum_h
Definition: TimePropagator.hpp:50
TMatrix< Tensor< Scalar, 1, 1, Symmetry > > spectrum_v
Definition: TimePropagator.hpp:51
Definition: iPEPS.hpp:39
Definition: Stopwatch.hpp:42
std::string time_string(TimeUnit u=TimeUnit::NATURAL)
Definition: Stopwatch.hpp:90
std::chrono::seconds time()
Definition: Stopwatch.hpp:113
constexpr void on_exit(Verbosity policy, Args &&... args)
Definition: Logging.hpp:102
constexpr void on_entry(Verbosity policy, Args &&... args)
Definition: Logging.hpp:108
constexpr void per_iteration(Verbosity policy, Args &&... args)
Definition: Logging.hpp:114
std::string format_secs(std::chrono::duration< double, std::ratio< 1, 1 > > dts)
Definition: Stopwatch.hpp:25
Definition: bench.cpp:62
Definition: CTMOpts.hpp:28
auto info()
Definition: CTMOpts.hpp:62
std::size_t chi
Definition: CTMOpts.hpp:29
Definition: ImagOpts.hpp:32
std::vector< std::size_t > t_steps
Definition: ImagOpts.hpp:36
bool multi_init
Definition: ImagOpts.hpp:65
std::string load
Definition: ImagOpts.hpp:48
std::filesystem::path obs_directory
Definition: ImagOpts.hpp:62
Verbosity verbosity
Definition: ImagOpts.hpp:56
std::vector< std::size_t > init_t_steps
Definition: ImagOpts.hpp:68
auto info()
Definition: ImagOpts.hpp:105
double tol
Definition: ImagOpts.hpp:44
std::size_t init_chi
Definition: ImagOpts.hpp:70
bool resume
Definition: ImagOpts.hpp:46
std::vector< std::vector< std::size_t > > chis
Definition: ImagOpts.hpp:34
std::size_t seed
Definition: ImagOpts.hpp:52
Update update
Definition: ImagOpts.hpp:39
std::vector< std::size_t > init_Ds
Definition: ImagOpts.hpp:67
std::vector< std::size_t > Ds
Definition: ImagOpts.hpp:33
std::size_t id
Definition: ImagOpts.hpp:54
LoadFormat load_format
Definition: ImagOpts.hpp:49
std::vector< double > init_dts
Definition: ImagOpts.hpp:69
std::size_t min_steps
Definition: ImagOpts.hpp:42
std::filesystem::path working_directory
Definition: ImagOpts.hpp:58
std::vector< double > dts
Definition: ImagOpts.hpp:37
std::vector< std::size_t > init_seeds
Definition: ImagOpts.hpp:66
bool display_obs
Definition: ImagOpts.hpp:63
int qn_scale
Definition: ImagOpts.hpp:50
Definition: TMatrix.hpp:13
std::size_t size() const
Definition: TMatrix.hpp:38
auto end()
Definition: TMatrix.hpp:68
auto begin()
Definition: TMatrix.hpp:67
Definition: TwoSiteObservable.hpp:22
Definition: iPEPSSolverImag.hpp:13
void init_psi()
Definition: iPEPSSolverImag.hpp:191
Opts::Imag imag_opts
Definition: iPEPSSolverImag.hpp:283
CTMSolver< Scalar, Symmetry > Jack
Definition: iPEPSSolverImag.hpp:282
void solve()
Definition: iPEPSSolverImag.hpp:65
iPEPSSolverImag(Opts::Imag imag_opts, Opts::CTM ctm_opts, std::shared_ptr< iPEPS< Scalar, Symmetry > > Psi_in, Hamiltonian< Symmetry > &H_in)
Definition: iPEPSSolverImag.hpp:19
Hamiltonian< Symmetry > & H
Definition: iPEPSSolverImag.hpp:285
std::shared_ptr< iPEPS< Scalar, Symmetry > > Psi
Definition: iPEPSSolverImag.hpp:284