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
22#include "./mesh.hpp"
23#include "../gfs/gf/gf.hpp"
24#include "../gfs/gf/gf_view.hpp"
26#include "../gfs/gf/targets.hpp"
31
32#include <c2py/converters/stl/vector.hpp>
33#include <c2py/py_converter.hpp>
34#include <c2py/pyref.hpp>
35#include <Python.h>
36
37#include <sstream>
38#include <stdexcept>
39#include <string>
40#include <vector>
41
43namespace c2py {
44
45 namespace detail {
46
47 // Non-template core: builds and raises the TypeError. Called by the thin template wrappers below.
48 inline void set_err_impl(PyObject *p, std::string_view kind, const char *X, std::string const &self_type, std::string const &C) {
49 std::ostringstream err;
50 err << "C2py converter: Python to C++ :\n"
51 << " ... Conversion of a " << kind << " from Python to C++ " << self_type << "\n"
52 << " ... Cannot convert the " << X << " of " << kind << " from Python type : " << p->ob_type->tp_name << " to the C++ type " << C;
53 PyErr_SetString(PyExc_TypeError, err.str().c_str());
54 }
55
56 } // namespace detail
57
58 // -----------------------------------
59 // gf
60 // -----------------------------------
61
62 template <typename M, typename T> struct py_converter<triqs::gfs::gf<M, T>> {
63 using c_t = triqs::gfs::gf<M, T>;
64 using conv_t = py_converter<triqs::gfs::gf_view<M, T>>;
65
66 static std::string tp_name() { return conv_t::tp_name(); }
67
68 static PyObject *c2py(triqs::gfs::gf_view<M, T> g) { return conv_t::c2py(g); }
69 static bool is_convertible(PyObject *ob, bool raise_exception) { return conv_t::is_convertible(ob, raise_exception); }
70 static c_t py2c(PyObject *ob) { return c_t{conv_t::py2c(ob)}; }
71 };
72
73 // -----------------------------------
74 // gf_const_view
75 // -----------------------------------
76
77 template <typename M, typename T> struct py_converter<triqs::gfs::gf_const_view<M, T>> {
78 using c_t = triqs::gfs::gf_const_view<M, T>;
79 using conv_t = py_converter<triqs::gfs::gf_view<M, T>>;
80
81 static std::string tp_name() { return conv_t::tp_name(); }
82
83 static PyObject *c2py(c_t g) = delete; // You can not convert a C++ const_view to a Python Gf ! Violates const correctness.
84 static bool is_convertible(PyObject *ob, bool raise_exception) { return conv_t::is_convertible(ob, raise_exception); }
85 static c_t py2c(PyObject *ob) { return conv_t::py2c(ob); }
86 };
87
88 // -----------------------------------
89 // gf_view
90 // -----------------------------------
91
92 // Converter for gf one var
93 template <typename M, typename T> struct py_converter<triqs::gfs::gf_view<M, T>> {
94 using c_t = triqs::gfs::gf_view<M, T>;
95 using mesh_t = typename c_t::mesh_t;
96 using data_t = typename c_t::data_t;
97
98 static std::string tp_name() {
99 std::ostringstream out;
100 out << "Gf[" << ::c2py::python_typename<M>() << ", " << T::rank << "]";
101 return out.str();
102 }
103
104 static PyObject *c2py(c_t g) {
105
106 pyref cls = pyref::get_class("triqs.gfs", "Gf", true);
107 if (cls.is_null()) return NULL;
108 pyref m = cxx2py(g.mesh());
109 if (m.is_null()) return NULL;
110 pyref d = cxx2py(g.data());
111 if (d.is_null()) return NULL;
112
113 pyref kw = PyDict_New();
114 PyDict_SetItemString(kw, "mesh", m);
115 PyDict_SetItemString(kw, "data", d);
116
117 pyref empty_tuple = PyTuple_New(0);
118 return PyObject_Call(cls, empty_tuple, kw);
119 }
120
121 // ----------------------------------------------
122
123 static void _set_err(PyObject *p, const char *X, std::string const &C) {
124 detail::set_err_impl(p, "Gf", X, triqs::utility::typeid_name<triqs::gfs::gf_view<M, T>>(), C);
125 }
126
127 // ----------------------------------------------
128
129 static bool is_convertible(PyObject *ob, bool raise_exception) {
130 pyref cls = pyref::get_class("triqs.gfs", "Gf", true);
131
132 // first check it is a Gf
133 if (not pyref::check_is_instance(ob, cls, raise_exception)) return false;
134 pyref x = pyref::borrowed(ob);
135
136 // check the mesh, data, indices
137 pyref m = x.attr("_mesh");
138 if (!py_converter<mesh_t>::is_convertible(m, false)) {
139 if (raise_exception) _set_err(m, "mesh", triqs::utility::typeid_name<mesh_t>());
140 return false;
141 }
142
143 pyref d = x.attr("_data");
144 if (!py_converter<data_t>::is_convertible(d, raise_exception)) {
145 if (raise_exception) _set_err(d, "data", triqs::utility::typeid_name<data_t>());
146 return false;
147 }
148
149 return true;
150 }
151
152 // ----------------------------------------------
153
154 static c_t py2c(PyObject *ob) {
155 pyref x = pyref::borrowed(ob);
156 pyref m = x.attr("_mesh");
157 pyref d = x.attr("_data");
158 return c_t{py2cxx<mesh_t>(m), py2cxx<data_t>(d)};
159 }
160 };
161
162 // -----------------------------------
163 // block_gf
164 // -----------------------------------
165
166 template <typename M, typename T, int A> struct py_converter<triqs::gfs::block_gf<M, T, nda::C_layout, A>> {
167 using conv_t = py_converter<triqs::gfs::block_gf_view<M, T, nda::C_stride_layout, A>>;
168 using c_t = triqs::gfs::block_gf<M, T, nda::C_layout, A>;
169
170 // ------------ tp_name ---------------
171
172 static std::string tp_name() { return conv_t::tp_name(); }
173
174 static PyObject *c2py(triqs::gfs::block_gf_view<M, T, nda::C_stride_layout, A> g) { return conv_t::c2py(g); }
175 static bool is_convertible(PyObject *ob, bool raise_exception) { return conv_t::is_convertible(ob, raise_exception); }
176 static c_t py2c(PyObject *ob) { return c_t{conv_t::py2c(ob)}; }
177 };
178
179 // -----------------------------------
180 // block_gf_const_view
181 // -----------------------------------
182
183 template <typename M, typename T, int A> struct py_converter<triqs::gfs::block_gf_const_view<M, T, nda::C_stride_layout, A>> {
184 using conv_t = py_converter<triqs::gfs::block_gf_view<M, T, nda::C_stride_layout, A>>;
186
187 // ------------ tp_name ---------------
188
189 static std::string tp_name() { return conv_t::tp_name(); }
190
191 static PyObject *c2py(c_t g) = delete; // You can not convert a C++ const_view to a Python Gf ! Violates const correctness.
192 static bool is_convertible(PyObject *ob, bool raise_exception) { return conv_t::is_convertible(ob, raise_exception); }
193 static c_t py2c(PyObject *ob) { return conv_t::py2c(ob); }
194 };
195
196 // -----------------------------------
197 // block_gf_view
198 // -----------------------------------
199
200 template <typename M, typename T> struct py_converter<triqs::gfs::block_gf_view<M, T>> {
201 using gf_type = triqs::gfs::gf<M, T>;
202 using gf_view_type = triqs::gfs::gf_view<M, T>;
203 using c_t = triqs::gfs::block_gf_view<M, T>;
204
205 static std::string tp_name() {
206 std::ostringstream out;
207 out << "BlockGf[" << ::c2py::python_typename<M>() << ", " << T::rank << "]";
208 return out.str();
209 }
210
211 // ----------------------------------------------
212
213 static PyObject *c2py(c_t g) {
214 // rm the view_proxy
215 std::vector<gf_view_type> vg;
216 vg.reserve(g.data().size());
217 for (auto const &x : g.data()) vg.push_back(x);
218 pyref v_gf = cxx2py(vg);
219 pyref v_names = cxx2py(g.block_names());
220 if (v_gf.is_null() or v_names.is_null()) return NULL;
221 pyref cls = pyref::module("triqs.gfs").attr("BlockGf");
222 if (cls.is_null()) return NULL;
223 pyref kw = PyDict_New();
224 PyDict_SetItemString(kw, "name_list", v_names);
225 PyDict_SetItemString(kw, "block_list", v_gf);
226 pyref empty_tuple = PyTuple_New(0);
227 return PyObject_Call(cls, empty_tuple, kw);
228 }
229
230 // ----------------------------------------------
231
232 static void _set_err(PyObject *p, const char *X, std::string const &C) {
233 detail::set_err_impl(p, "BlockGf", X, triqs::utility::typeid_name<c_t>(), C);
234 }
235
236 // ----------------------------------------------
237
238 static bool is_convertible(PyObject *ob, bool raise_exception) {
239 pyref cls = pyref::get_class("triqs.gfs", "BlockGf", true);
240
241 // first check it is a BlockGf
242 if (not pyref::check_is_instance(ob, cls, raise_exception)) return false;
243 pyref x = pyref::borrowed(ob);
244
245 // check the gfs and indices
246 pyref gfs = x.attr("_BlockGf__GFlist");
247 if (!py_converter<std::vector<gf_view_type>>::is_convertible(gfs, false)) {
248 if (raise_exception) _set_err(gfs, "_BlockGf__GFlist", triqs::utility::typeid_name<std::vector<gf_view_type>>());
249 return false;
250 }
251
252 pyref names = x.attr("_BlockGf__indices");
253 if (!py_converter<std::vector<std::string>>::is_convertible(names, false)) {
254 if (raise_exception) _set_err(names, "_BlockGf__indices", triqs::utility::typeid_name<std::vector<std::string>>());
255 return false;
256 }
257
258 return true;
259 }
260
261 // ----------------------------------------------
262
263 static c_t py2c(PyObject *ob) {
264 pyref x = pyref::borrowed(ob);
265 pyref names = x.attr("_BlockGf__indices");
266 pyref gfs = x.attr("_BlockGf__GFlist");
267 return make_block_gf_view(py2cxx<std::vector<std::string>>(names), py2cxx<std::vector<gf_view_type>>(gfs));
268 }
269 };
270
271 // -----------------------------------
272 // block2_gf_view
273 // -----------------------------------
274
275 template <typename M, typename T> struct py_converter<triqs::gfs::block2_gf_view<M, T>> {
276 using gf_type = triqs::gfs::gf<M, T>;
277 using gf_view_type = triqs::gfs::gf_view<M, T>;
279
280 static std::string tp_name() {
281 std::ostringstream out;
282 out << "Block2Gf[" << ::c2py::python_typename<M>() << ", " << T::rank << "]";
283 return out.str();
284 }
285
286 // ----------------------------------------------
287
288 static PyObject *c2py(c_t g) {
289 std::vector<std::vector<gf_view_type>> vvg;
290 vvg.reserve(g.data().size());
291 for (auto const &x : g.data()) {
292 std::vector<gf_view_type> vg;
293 vg.reserve(x.size());
294 for (auto const &y : x) vg.push_back(y);
295 vvg.push_back(vg);
296 }
297 pyref v_gf = cxx2py(vvg);
298 pyref v_names1 = cxx2py(g.block_names()[0]);
299 pyref v_names2 = cxx2py(g.block_names()[1]);
300 if (v_gf.is_null() or v_names1.is_null() or v_names2.is_null()) return NULL;
301 pyref cls = pyref::module("triqs.gfs").attr("Block2Gf");
302 if (cls.is_null()) return NULL;
303 pyref args = PyTuple_Pack(3, (PyObject *)v_names1, (PyObject *)v_names2, (PyObject *)v_gf);
304 return PyObject_Call(cls, args, NULL);
305 }
306
307 // ----------------------------------------------
308
309 static bool is_convertible(PyObject *ob, bool raise_exception) {
310 pyref cls = pyref::get_class("triqs.gfs", "Block2Gf", true);
311 if (cls.is_null()) throw std::runtime_error("Cannot find the triqs.gfs.Block2Gf");
312
313 // first check it is a Block2Gf
314 if (not pyref::check_is_instance(ob, cls, raise_exception)) return false;
315
316 pyref x = pyref::borrowed(ob);
317 pyref gfs = x.attr("_Block2Gf__GFlist");
318 return py_converter<std::vector<std::vector<gf_view_type>>>::is_convertible(gfs, raise_exception);
319 }
320
321 // ----------------------------------------------
322
323 static c_t py2c(PyObject *ob) {
324 pyref x = pyref::borrowed(ob);
325 pyref names1 = x.attr("_Block2Gf__indices1");
326 pyref names2 = x.attr("_Block2Gf__indices2");
327 pyref gfs = x.attr("_Block2Gf__GFlist");
328 return make_block2_gf_view(py2cxx<std::vector<std::string>>(names1), py2cxx<std::vector<std::string>>(names2),
329 py2cxx<std::vector<std::vector<gf_view_type>>>(gfs));
330 }
331 };
332
333} // namespace c2py
Provides the block Green's function container.
Provides a non-owning view of a block Green's function.
Provides the free factory functions for block Green's functions.
Provides the triqs::gfs::gf_const_view container, a read-only non-owning view of a Green's function.
Provides a mutable non-owning view of a Green's function.
Provides the Green's function class.
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.
Additional converters for gf.
Provides the target types that fix the value stored at each mesh point of a Green's function.
Helper functions built around std::type_info.