TRIQS/TRIQS 4.0.0
Researching Interacting Quantum Systems
Loading...
Searching...
No Matches
many_body_operator.cpp
Go to the documentation of this file.
1// Copyright (c) 2015-2018 Commissariat à l'énergie atomique et aux énergies alternatives (CEA)
2// Copyright (c) 2015-2018 Centre national de la recherche scientifique (CNRS)
3// Copyright (c) 2018-2023 Simons Foundation
4//
5// This program is free software: you can redistribute it and/or modify
6// it under the terms of the GNU General Public License as published by
7// the Free Software Foundation, either version 3 of the License, or
8// (at your option) any later version.
9//
10// This program is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13// GNU General Public License for more details.
14//
15// You may obtain a copy of the License at
16// https://www.gnu.org/licenses/gpl-3.0.txt
17//
18// Authors: Michel Ferrero, Olivier Parcollet, Nils Wentzell
19
24
28
29#include <fmt/ostream.h>
30#include <h5/h5.hpp>
31#include <hdf5.h>
32#include <itertools/itertools.hpp>
33
34#include <algorithm>
35#include <array>
36#include <cmath>
37#include <complex>
38#include <cstddef>
39#include <ostream>
40#include <string>
41#include <vector>
42
43namespace triqs::operators {
44
45 using h5::dataset;
46 using h5::object;
47 using hilbert_space::fundamental_operator_set;
48
49// maximum order of the monomial (here quartic operators)
50#define MAX_MONOMIAL_SIZE 4
51
52 std::ostream &operator<<(std::ostream &sout, canonical_ops_t const &op) {
54 fmt::print(sout, "c{}{}", (op.dagger ? "_dag" : ""), format_indices(op.indices, ",", "(", ")"));
55 return sout;
56 }
57
58 bool operator<(monomial_t const &m1, monomial_t const &m2) {
59 return m1.size() != m2.size() ? m1.size() < m2.size() : std::ranges::lexicographical_compare(m1, m2);
60 }
61
62 std::ostream &operator<<(std::ostream &os, monomial_t const &m) {
63 for (auto const &c : m) { os << '*' << c; }
64 return os;
65 }
66
67 namespace {
68
69 // the type of the monomial to be stored in the h5 file
70 // the complicated indices of the C, C^ will be transformed into an int
71 // via a fundamental_operator_set
72 struct h5_monomial {
73 bool is_real{};
74 double re{};
75 double im{};
76 std::array<long, MAX_MONOMIAL_SIZE> op_indices{};
77 };
78
79 // create the h5 type corresponding to h5_monomial
80 object h5_monomial_dtype() {
81 object mono_obj = H5Tcreate(H5T_COMPOUND, sizeof(h5_monomial));
82 H5Tinsert(mono_obj, "is_real", HOFFSET(h5_monomial, is_real), H5T_NATIVE_INT);
83 H5Tinsert(mono_obj, "re", HOFFSET(h5_monomial, re), H5T_NATIVE_DOUBLE);
84 H5Tinsert(mono_obj, "im", HOFFSET(h5_monomial, im), H5T_NATIVE_DOUBLE);
85 std::array<h5::hsize_t, 1> array_dim{MAX_MONOMIAL_SIZE};
86 h5::object array_tid = H5Tarray_create(H5T_NATIVE_LONG, 1, array_dim.data());
87 H5Tinsert(mono_obj, "op_indices", HOFFSET(h5_monomial, op_indices), array_tid);
88 return mono_obj;
89 }
90 } // namespace
91
92 // --------------------------- WRITE -----------------------------------------
93
94 void h5_write(h5::group g, std::string const &name, many_body_operator const &op, fundamental_operator_set const &fops) {
95
96 // first prepare the data
97 // datavec stores all monomials.
98 // In each monomial, the C, C^+ operator is labeled by an int,
99 // >0 for C^+, <0 for C. 0 means : no operator.
100 // Its abs is the unique int associated to the series of indices of the C, from the fundamental_operator_set
101 std::vector<h5_monomial> datavec;
102
103 for (auto const &m : op.monomials_) { // for all monomials of the operator
104 if (m.first.size() > MAX_MONOMIAL_SIZE)
105 TRIQS_RUNTIME_ERROR << " h5 writing many_body_operator : unexpected monomial with more than " << MAX_MONOMIAL_SIZE << "operators !";
106 h5_monomial y = {.is_real = m.second.is_real(), .re = real(m.second), .im = imag(m.second), .op_indices = {0, 0, 0, 0}};
107 int i = 0;
108 for (auto const &c_cdag_op : m.first) { // loop over the C C^+ operators of the monomial
109 long c_number = fops[c_cdag_op.indices] + 1; // the number of the C C^+ op. 0 means "no operators" here, so we shift by 1
110 y.op_indices[i++] = (c_cdag_op.dagger ? c_number : -c_number);
111 }
112 datavec.push_back(y);
113 }
114 // now datavec and correspondance_table are ready.
115
116 // ----- Store datavec into the h5 file.
117
118 // datatype
119 object dt = h5_monomial_dtype();
120
121 // dataspace
122 std::array<hsize_t, 1> dim{datavec.size()};
123 object dspace = H5Screate_simple(1, dim.data(), nullptr);
124
125 // dataset
126 object ds = g.create_dataset(name.c_str(), dt, dspace);
127
128 // write
129 herr_t status = H5Dwrite(ds, dt, H5S_ALL, H5S_ALL, H5P_DEFAULT, datavec.data());
130 if (status < 0) TRIQS_RUNTIME_ERROR << "Error writing the many_body_operator " << op << " in the group" << g.name();
131
132 // Store fundamental_operator_set as an attribute of the dataset
133 h5::write_attribute(ds, "fundamental_operator_set", fops);
134 write_hdf5_format(ds, op);
135 }
136
137 // --------------------------- READ -----------------------------------------
138
139 void h5_read(h5::group g, std::string const &name, many_body_operator &op, fundamental_operator_set &fops) {
140
141 // --- Read the datavec
142
143 // open the dataset
144 dataset ds = g.open_dataset(name);
145
146 // dataspace
147 h5::dataspace dspace = H5Dget_space(ds);
148
149 // recover the dimension: must be of rank 1
150 std::array<hsize_t, 1> dims_out{};
151 int ndims = H5Sget_simple_extent_dims(dspace, dims_out.data(), nullptr);
152 if (ndims != 1)
153 TRIQS_RUNTIME_ERROR << "h5 : Trying to read many_body_operator. Rank mismatch : the array stored in the hdf5 file has rank = " << ndims;
154
155 // datatype
156 object dt = h5_monomial_dtype();
157
158 // reading
159 std::vector<h5_monomial> datavec(dims_out[0]);
160
161 herr_t status = H5Dread(ds, h5_monomial_dtype(), dspace, H5S_ALL, H5P_DEFAULT, datavec.data());
162 if (status < 0) TRIQS_RUNTIME_ERROR << "Error reading the many_body_operator " << op << " from the group" << g.name();
163
164 // --- Read correspondance_table as an attribute
165 h5::read_attribute(ds, "fundamental_operator_set", fops);
166
167 // ---- Now we must reverse the operations of write
168
169 auto r_fops = fops.data(); // the data vector v[int] -> indices inverting fops[indices] -> n
170
171 for (auto const &mon : datavec) {
172 monomial_t monomial; // vector of canonical_ops_t
173 for (long i : mon.op_indices) { // loop over the index of the C, C^ ops of the monomial
174 if (i == 0) break; // means we have reach the end of the C, C^+ list
175 monomial.push_back({.dagger = (i > 0), .indices = r_fops[std::abs(i) - 1]}); // add one C, C^+ op to the monomial
176 }
177 real_or_complex s = (mon.is_real ? real_or_complex(mon.re) : real_or_complex(std::complex<double>(mon.re, mon.im)));
178 op.monomials_.insert({monomial, s}); // add the monomial to the operator
179 }
180 }
181
182} // namespace triqs::operators
Class representing a fundamental operator set.
friend void h5_read(h5::group g, std::string const &name, many_body_operator &op, hilbert_space::fundamental_operator_set &fops)
friend void h5_write(h5::group g, std::string const &name, many_body_operator const &op, hilbert_space::fundamental_operator_set const &fops)
Type that can represent either a real or a complex number.
std::string format_indices(indices_t const &alpha, std::string_view sep, std::string_view prefix, std::string_view suffix)
String representation of a single particle state index .
many_body_operator_generic< T > real(many_body_operator_generic< T > const &op)
Get a copy of the given operator with the imaginary parts of all monomial coefficients set to zero.
many_body_operator_generic< real_or_complex > many_body_operator
Many-body operator with real or complex coefficients (see triqs::operators::many_body_operator_generi...
std::vector< canonical_ops_t > monomial_t
Type used to represent a monomial of canonical second quantization operators.
many_body_operator_generic< T > imag(many_body_operator_generic< T > const &op)
Get a copy of the given operator with the real parts of all monomial coefficients set to zero.
bool operator<(monomial_t const &m1, monomial_t const &m2)
Less-than comparison operator for triqs::operators::monomial_t.
many_body_operator_generic< T > c(IndexTypes... indices)
Create an annihilation operator .
std::ostream & operator<<(std::ostream &sout, canonical_ops_t const &op)
Write a triqs::operators::canonical_ops_t to a std::ostream.
#define TRIQS_RUNTIME_ERROR
Throw a triqs::runtime_error with the current source location.
Provides a fundamental operator set class.
Provides generic many-body operators.
Second quantization creation/annihilation operator.
indices_t indices
Single particle state index .
bool dagger
True for creation ( ), false for annihilation ( ) operators.
Provides a type that decides at runtime whether it is real or complex.