TRIQS/TRIQS 4.0.0
Researching Interacting Quantum Systems
Loading...
Searching...
No Matches
gf.hpp
1// Copyright (c) 2017 Commissariat à l'énergie atomique et aux énergies alternatives (CEA)
2// Copyright (c) 2017 Centre national de la recherche scientifique (CNRS)
3// Copyright (c) 2020-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: Alexander Hampel, Olivier Parcollet, Nils Wentzell
19
20#pragma once
21#include <triqs/gfs.hpp>
22#include <triqs/mesh/utils.hpp>
24#include <triqs/cpp2py_converters/arrays.hpp>
25
26#include <cpp2py/misc.hpp>
27#include <cpp2py/converters/vector.hpp>
28#include <cpp2py/converters/tuple.hpp>
29#include <cpp2py/converters/std_array.hpp>
30#include <cpp2py/converters/string.hpp>
31
32#include "./mesh.hpp"
33
35namespace cpp2py {
36
37 // -----------------------------------
38 // is_view
39 // One MUST declare to cpp2py that a type is a view.
40 // -----------------------------------
41
42 template <typename M, typename T> struct is_view<triqs::gfs::gf_view<M, T>> : std::true_type {};
43 template <typename M, typename T> struct is_view<triqs::gfs::gf_const_view<M, T>> : std::true_type {};
44
45 template <typename M, typename T, typename L, int A, bool C> struct is_view<triqs::gfs::block_gf_view<M, T, L, A, C>> : std::true_type {};
46
47 // -----------------------------------
48 // gf
49 // -----------------------------------
50
51 template <typename M, typename T> struct py_converter<triqs::gfs::gf<M, T>> {
52 using c_t = triqs::gfs::gf<M, T>;
53 using conv_t = py_converter<triqs::gfs::gf_view<M, T>>;
54
55#ifdef C2PY_INCLUDED
56 static std::string tp_name() { return conv_t::tp_name(); }
57#endif
58
59 static PyObject *c2py(triqs::gfs::gf_view<M, T> g) { return conv_t::c2py(g); }
60 static bool is_convertible(PyObject *ob, bool raise_exception) { return conv_t::is_convertible(ob, raise_exception); }
61 static c_t py2c(PyObject *ob) { return c_t{conv_t::py2c(ob)}; }
62 };
63
64 // -----------------------------------
65 // gf_const_view
66 // -----------------------------------
67
68 template <typename M, typename T> struct py_converter<triqs::gfs::gf_const_view<M, T>> {
69 using c_t = triqs::gfs::gf_const_view<M, T>;
70 using conv_t = py_converter<triqs::gfs::gf_view<M, T>>;
71
72#ifdef C2PY_INCLUDED
73 static std::string tp_name() { return conv_t::tp_name(); }
74#endif
75
76 static PyObject *c2py(c_t g) = delete; // You can not convert a C++ const_view to a Python Gf ! Violates const correctness.
77 static bool is_convertible(PyObject *ob, bool raise_exception) { return conv_t::is_convertible(ob, raise_exception); }
78 static c_t py2c(PyObject *ob) { return conv_t::py2c(ob); }
79 };
80
81 // -----------------------------------
82 // gf_view
83 // -----------------------------------
84
85 // Converter for gf one var
86 template <typename M, typename T> struct py_converter<triqs::gfs::gf_view<M, T>> {
87 using c_t = triqs::gfs::gf_view<M, T>;
88 using mesh_t = typename c_t::mesh_t;
89 using data_t = typename c_t::data_t;
90
91#ifdef C2PY_INCLUDED
92 static std::string tp_name() {
93 std::ostringstream out;
94 out << "Gf[" << ::c2py::python_typename<M>() << ", " << T::rank << "]";
95 return out.str();
96 }
97#endif
98
99 static PyObject *c2py(c_t g) {
100
101 pyref cls = pyref::get_class("triqs.gfs", "Gf", true);
102 if (cls.is_null()) return NULL;
103 pyref m = convert_to_python(g.mesh());
104 if (m.is_null()) return NULL;
105 pyref d = convert_to_python(g.data());
106 if (d.is_null()) return NULL;
107
108 pyref kw = PyDict_New();
109 PyDict_SetItemString(kw, "mesh", m);
110 PyDict_SetItemString(kw, "data", d);
111
112 pyref empty_tuple = PyTuple_New(0);
113 return PyObject_Call(cls, empty_tuple, kw);
114 }
115
116 // ----------------------------------------------
117
118 static void _set_err(PyObject *p, const char *X, std::string const &C) {
119 using namespace std::string_literals;
120 std::string err = "Cpp2py converter: Python to C++ :\n"s + " ... Conversion of a Gf from Python to C++ "
121 + triqs::utility::typeid_name<triqs::gfs::gf_view<M, T>>() + "\n ... Cannot convert the "s + X
122 + " of Gf from Python type : " + p->ob_type->tp_name + " to the C++ type " + C;
123 PyErr_SetString(PyExc_TypeError, err.c_str());
124 }
125
126 // ----------------------------------------------
127
128 static bool is_convertible(PyObject *ob, bool raise_exception) {
129 pyref cls = pyref::get_class("triqs.gfs", "Gf", true);
130
131 // first check it is a Gf
132 if (not pyref::check_is_instance(ob, cls, raise_exception)) return false;
133 pyref x = borrowed(ob);
134
135 // check the mesh, data, indices
136 pyref m = x.attr("_mesh");
137 if (!py_converter<mesh_t>::is_convertible(m, false)) {
138 if (raise_exception) _set_err(m, "mesh", triqs::utility::typeid_name<mesh_t>());
139 return false;
140 }
141
142 pyref d = x.attr("_data");
143 if (!py_converter<data_t>::is_convertible(d, raise_exception)) {
144 if (raise_exception) _set_err(d, "data", triqs::utility::typeid_name<data_t>());
145 return false;
146 }
147
148 return true;
149 }
150
151 // ----------------------------------------------
152
153 static c_t py2c(PyObject *ob) {
154 pyref x = borrowed(ob);
155 pyref m = x.attr("_mesh");
156 pyref d = x.attr("_data");
157 return c_t{convert_from_python<mesh_t>(m), convert_from_python<data_t>(d)};
158 }
159 };
160
161 // -----------------------------------
162 // block_gf
163 // -----------------------------------
164
165 template <typename M, typename T, int A> struct py_converter<triqs::gfs::block_gf<M, T, nda::C_layout, A>> {
166 using conv_t = py_converter<triqs::gfs::block_gf_view<M, T, nda::C_stride_layout, A>>;
167 using c_t = triqs::gfs::block_gf<M, T, nda::C_layout, A>;
168
169 // ------------ tp_name ---------------
170
171#ifdef C2PY_INCLUDED
172 static std::string tp_name() { return conv_t::tp_name(); }
173#endif
174
175 static PyObject *c2py(triqs::gfs::block_gf_view<M, T, nda::C_stride_layout, A> g) { return conv_t::c2py(g); }
176 static bool is_convertible(PyObject *ob, bool raise_exception) { return conv_t::is_convertible(ob, raise_exception); }
177 static c_t py2c(PyObject *ob) { return c_t{conv_t::py2c(ob)}; }
178 };
179
180 // -----------------------------------
181 // block_gf_const_view
182 // -----------------------------------
183
184 template <typename M, typename T, int A> struct py_converter<triqs::gfs::block_gf_const_view<M, T, nda::C_stride_layout, A>> {
185 using conv_t = py_converter<triqs::gfs::block_gf_view<M, T, nda::C_stride_layout, A>>;
187
188 // ------------ tp_name ---------------
189
190#ifdef C2PY_INCLUDED
191 static std::string tp_name() { return conv_t::tp_name(); }
192#endif
193
194 static PyObject *c2py(c_t g) = delete; // You can not convert a C++ const_view to a Python Gf ! Violates const correctness.
195 static bool is_convertible(PyObject *ob, bool raise_exception) { return conv_t::is_convertible(ob, raise_exception); }
196 static c_t py2c(PyObject *ob) { return conv_t::py2c(ob); }
197 };
198
199 // -----------------------------------
200 // block_gf_view
201 // -----------------------------------
202
203 template <typename M, typename T> struct py_converter<triqs::gfs::block_gf_view<M, T>> {
204 using gf_type = triqs::gfs::gf<M, T>;
205 using gf_view_type = triqs::gfs::gf_view<M, T>;
206 using c_t = triqs::gfs::block_gf_view<M, T>;
207
208#ifdef C2PY_INCLUDED
209 static std::string tp_name() {
210 std::ostringstream out;
211 out << "BlockGf[" << ::c2py::python_typename<M>() << ", " << T::rank << "]";
212 return out.str();
213 }
214#endif
215
216 // ----------------------------------------------
217
218 static PyObject *c2py(c_t g) {
219 // rm the view_proxy
220 std::vector<gf_view_type> vg;
221 vg.reserve(g.data().size());
222 for (auto const &x : g.data()) vg.push_back(x);
223 pyref v_gf = convert_to_python(vg);
224 pyref v_names = convert_to_python(g.block_names());
225 if (v_gf.is_null() or v_names.is_null()) return NULL;
226 pyref cls = pyref::module("triqs.gfs").attr("BlockGf");
227 if (cls.is_null()) return NULL;
228 pyref kw = PyDict_New();
229 PyDict_SetItemString(kw, "name_list", v_names);
230 PyDict_SetItemString(kw, "block_list", v_gf);
231 pyref empty_tuple = PyTuple_New(0);
232 return PyObject_Call(cls, empty_tuple, kw);
233 }
234
235 // ----------------------------------------------
236
237 static void _set_err(PyObject *p, const char *X, std::string const &C) {
238 using namespace std::string_literals;
239 std::string err = "Cpp2py converter: Python to C++ :\n"s + " ... Conversion of a BlockGf from Python to C++ "
240 + triqs::utility::typeid_name<c_t>() + "\n ... Cannot convert the "s + X + " of BlockGf from Python type : " + p->ob_type->tp_name
241 + " to the C++ type " + C;
242 PyErr_SetString(PyExc_TypeError, err.c_str());
243 }
244
245 // ----------------------------------------------
246
247 static bool is_convertible(PyObject *ob, bool raise_exception) {
248 pyref cls = pyref::get_class("triqs.gfs", "BlockGf", true);
249
250 // first check it is a BlockGf
251 if (not pyref::check_is_instance(ob, cls, raise_exception)) return false;
252 pyref x = borrowed(ob);
253
254 // check the gfs and indices
255 pyref gfs = x.attr("_BlockGf__GFlist");
256 if (!py_converter<std::vector<gf_view_type>>::is_convertible(gfs, false)) {
257 if (raise_exception) _set_err(gfs, "_BlockGf__GFlist", triqs::utility::typeid_name<std::vector<gf_view_type>>());
258 return false;
259 }
260
261 pyref names = x.attr("_BlockGf__indices");
262 if (!py_converter<std::vector<std::string>>::is_convertible(names, false)) {
263 if (raise_exception) _set_err(names, "_BlockGf__indices", triqs::utility::typeid_name<std::vector<std::string>>());
264 return false;
265 }
266
267 return true;
268 }
269
270 // ----------------------------------------------
271
272 static c_t py2c(PyObject *ob) {
273 pyref x = borrowed(ob);
274 pyref names = x.attr("_BlockGf__indices");
275 pyref gfs = x.attr("_BlockGf__GFlist");
276 return make_block_gf_view(convert_from_python<std::vector<std::string>>(names), convert_from_python<std::vector<gf_view_type>>(gfs));
277 }
278 };
279
280 // -----------------------------------
281 // block2_gf_view
282 // -----------------------------------
283
284 template <typename M, typename T> struct py_converter<triqs::gfs::block2_gf_view<M, T>> {
285 using gf_type = triqs::gfs::gf<M, T>;
286 using gf_view_type = triqs::gfs::gf_view<M, T>;
288
289#ifdef C2PY_INCLUDED
290 static std::string tp_name() {
291 std::ostringstream out;
292 out << "Block2Gf[" << ::c2py::python_typename<M>() << ", " << T::rank << "]";
293 return out.str();
294 }
295#endif
296
297 // ----------------------------------------------
298
299 static PyObject *c2py(c_t g) {
300 std::vector<std::vector<gf_view_type>> vvg;
301 vvg.reserve(g.data().size());
302 for (auto const &x : g.data()) {
303 std::vector<gf_view_type> vg;
304 vg.reserve(x.size());
305 for (auto const &y : x) vg.push_back(y);
306 vvg.push_back(vg);
307 }
308 pyref v_gf = convert_to_python(vvg);
309 pyref v_names1 = convert_to_python(g.block_names()[0]);
310 pyref v_names2 = convert_to_python(g.block_names()[1]);
311 if (v_gf.is_null() or v_names1.is_null() or v_names2.is_null()) return NULL;
312 pyref cls = pyref::module("triqs.gfs").attr("Block2Gf");
313 if (cls.is_null()) return NULL;
314 pyref args = PyTuple_Pack(3, (PyObject *)v_names1, (PyObject *)v_names2, (PyObject *)v_gf);
315 return PyObject_Call(cls, args, NULL);
316 }
317
318 // ----------------------------------------------
319
320 static bool is_convertible(PyObject *ob, bool raise_exception) {
321 pyref cls = pyref::get_class("triqs.gfs", "Block2Gf", true);
322 if (cls.is_null()) throw std::runtime_error("Cannot find the triqs.gfs.Block2Gf");
323
324 // first check it is a Block2Gf
325 if (not pyref::check_is_instance(ob, cls, raise_exception)) return false;
326
327 pyref x = borrowed(ob);
328 pyref gfs = x.attr("_Block2Gf__GFlist");
329 return py_converter<std::vector<std::vector<gf_view_type>>>::is_convertible(gfs, raise_exception);
330 }
331
332 // ----------------------------------------------
333
334 static c_t py2c(PyObject *ob) {
335 pyref x = borrowed(ob);
336 pyref names1 = x.attr("_Block2Gf__indices1");
337 pyref names2 = x.attr("_Block2Gf__indices2");
338 pyref gfs = x.attr("_Block2Gf__GFlist");
339 return make_block2_gf_view(convert_from_python<std::vector<std::string>>(names1), convert_from_python<std::vector<std::string>>(names2),
340 convert_from_python<std::vector<std::vector<gf_view_type>>>(gfs));
341 }
342 };
343
344} // namespace cpp2py
Umbrella header for the Green's function library.
block_gf_view< Mesh, Target, Layout, Arity, true > block_gf_const_view
Const view alias for a block Green's function.
Definition block_gf.hpp:60
block_gf_view< Mesh, Target, Layout, 2, false > block2_gf_view
Mutable view of a two-index block Green's function.
Definition block_gf.hpp:81
block2_gf_view_of< Gf > make_block2_gf_view(std::vector< std::vector< Gf > > &v)
Make a triqs::gfs::block2_gf_view from a matrix of views (block names default to "0",...
block_gf_view_of< G0 > make_block_gf_view(G0 &&g0, G &&...g)
Make a triqs::gfs::block_gf_view from a list of Green's function views (block names default to "0",...
std::string typeid_name()
Human-readable name of a given static type.
Provides various utilities used with Meshes.
Additional converters for gf.
Helper functions built around std::type_info.