3
0
mirror of https://github.com/triqs/dft_tools synced 2024-12-25 05:43:40 +01:00

lattice : python wrapper

This commit is contained in:
Olivier Parcollet 2014-05-29 21:34:46 +02:00
parent 5f6dadfede
commit 2b5dd322ce
11 changed files with 175 additions and 129 deletions

View File

@ -6,7 +6,7 @@ SET(PYTHON_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/descriptors.py
${CMAKE_CURRENT_SOURCE_DIR}/_gf_imfreq.py
${CMAKE_CURRENT_SOURCE_DIR}/_gf_imtime.py
#${CMAKE_CURRENT_SOURCE_DIR}/_gf_legendre.py
${CMAKE_CURRENT_SOURCE_DIR}/_gf_legendre.py
${CMAKE_CURRENT_SOURCE_DIR}/_gf_refreq.py
${CMAKE_CURRENT_SOURCE_DIR}/_gf_retime.py
#${CMAKE_CURRENT_SOURCE_DIR}/gf_two_real_times.py

View File

@ -5,12 +5,10 @@ SET(PYTHON_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/tight_binding.py
)
install (FILES ${CMAKE_SOURCE_DIR}/pytriqs/__init__.py.template DESTINATION "include/pytriqs/gf/local" RENAME __init__.py)
install (FILES ${PYTHON_SOURCES} DESTINATION ${TRIQS_PYTHON_LIB_DEST}/lattice)
# THE C++ code
#SET(CPP_DIR ${CMAKE_CURRENT_SOURCE_DIR}/C++)
cython_module(LatticeTools lattice_tools lattice )
# ???
#target_link_libraries(_pytriqs_LatticeTools triqs ${TRIQS_LINK_LIBS})
# Build C extension module
triqs_python_extension(lattice_tools lattice)

View File

@ -1,116 +0,0 @@
from dcomplex cimport *
from shared_ptr cimport *
from arrays cimport *
from libcpp.pair cimport pair
from libcpp.vector cimport vector
from libcpp.string cimport string as std_string
#from extractor cimport *
#from h5 cimport *
from cython.operator cimport dereference as deref, preincrement as inc #dereference and increment operator
import numpy
cdef extern from "triqs/lattice/brillouin_zone.hpp" :
cdef cppclass bravais_lattice_c " triqs::lattice::bravais_lattice" :
bravais_lattice_c(matrix[double] & units, vector[tqa_vector[double]] &, vector[std_string] &) except +
int n_orbitals()
matrix[double] units()
int dim()
tqa_vector[double] lattice_to_real_coordinates (tqa_vector_view[double] &)
cdef extern from "triqs/lattice/tight_binding.hpp" namespace "triqs::gf" :
cdef cppclass tight_binding " triqs::lattice::tight_binding" :
tight_binding(bravais_lattice_c & units, vector[vector[long]] &, vector[matrix[dcomplex]] &) except +
#Fix the name conflict pv wiht a pxd, cf doc....?
array_view[complex,THREE] hopping_stack_c "hopping_stack" (tight_binding & TB, array_view[double,TWO] & k_stack)
pair [array[double,ONE],array[double,TWO]] dos_c "dos" (tight_binding & TB, size_t nkpts, size_t neps)
pair [array[double,ONE],array[double,ONE]] dos_patch_c "dos_patch" (tight_binding & TB, array_view[double,TWO] & triangles, size_t neps, size_t ndiv)
array_view[double,TWO] energies_on_bz_path_c "energies_on_bz_path" (tight_binding & TB, tqa_vector[double] & K1, tqa_vector[double] & K2, size_t n_pts)
array_view[complex,THREE] energy_matrix_on_bz_path_c "energy_matrix_on_bz_path" (tight_binding & TB, tqa_vector[double] & K1, tqa_vector[double] & K2, size_t n_pts)
array_view[double,TWO] energies_on_bz_grid_c "energies_on_bz_grid" (tight_binding & TB, size_t n_pts)
cdef class BravaisLattice :
"""
"""
cdef bravais_lattice_c * _c
def __init__(self, units, orbital_positions = None ) :
""" """
cdef vector[std_string] names
cdef vector[tqa_vector[double]] atom_pos
orbital_positions = orbital_positions if orbital_positions else dict ("", (0,0,0) )
for name, pos in orbital_positions.items():
names.push_back(name)
atom_pos.push_back(tqa_vector[double](pos))
self._c = new bravais_lattice_c( matrix[double](units),atom_pos, names)
def __dealloc__(self):
del self._c
def lattice_to_real_coordinates(self, R) :
"""
Transform into real coordinates.
:param x_in: coordinates in the basis of the unit vectors
:rtype: Output coordinates in R^3 (real coordinates) as an array
"""
return self._c.lattice_to_real_coordinates ( tqa_vector_view[double] (R)).to_python()
property dim :
"""Dimension of the lattice"""
def __get__(self) :
"""Dimension of the lattice"""
return self._c.dim()
def n_orbitals(self) :
"""Number of orbitals"""
return self._c.n_orbitals()
cdef class TightBinding:
"""
"""
cdef tight_binding * _c
def __init__(self, BravaisLattice bravais_lattice, hopping ) :
""" """
#self._c = new tight_binding(deref(bravais_lattice._c))
#cdef vector[long] d
cdef vector[matrix[dcomplex]] mats
cdef vector[vector[long]] displs
for displ, mat in hopping.items() :
displs.push_back(displ)
#d = displ
mats.push_back(matrix[dcomplex] (numpy.array(mat, dtype =float)))
#self._c.push_back( d, matrix[double] (numpy.array(mat, dtype =float)))
self._c = new tight_binding(deref(bravais_lattice._c), displs, mats)
def __dealloc__(self):
del self._c
# -------------------------------------------
def hopping_stack (TightBinding TB, k_stack) :
""" """
return hopping_stack_c(deref(TB._c), array_view[double,TWO](k_stack)).to_python()
def dos ( TightBinding TB, int nkpts, int neps):
""" """
a = dos_c(deref(TB._c), nkpts, neps)
return (a.first.to_python(), a.second.to_python())
def dos_patch ( TightBinding TB, triangles, int neps, int ndiv):
""" """
a = dos_patch_c(deref(TB._c), array_view[double,TWO] (triangles), neps, ndiv)
return (a.first.to_python(), a.second.to_python())
def energies_on_bz_path ( TightBinding TB, K1, K2, n_pts) :
""" """
return energies_on_bz_path_c (deref(TB._c), tqa_vector[double](K1), tqa_vector[double] (K2), n_pts).to_python()
def energy_matrix_on_bz_path ( TightBinding TB, K1, K2, n_pts) :
""" """
return energy_matrix_on_bz_path_c (deref(TB._c), tqa_vector[double](K1), tqa_vector[double] (K2), n_pts).to_python()
def energies_on_bz_grid ( TightBinding TB, n_pts) :
""" """
return energies_on_bz_grid_c (deref(TB._c), n_pts).to_python()

View File

@ -0,0 +1,105 @@
from wrap_generator import *
module = module_(full_name = "pytriqs.lattice_tools", doc = "Lattice tools (to be improved)")
module.add_include("<triqs/lattice/brillouin_zone.hpp>")
module.add_include("<triqs/lattice/tight_binding.hpp>")
module.add_using("namespace triqs::lattice")
module.add_using("namespace triqs::arrays")
module.add_using("namespace triqs")
module.add_using("r_t = arrays::vector<double>")
module.add_using("k_t = arrays::vector<double>")
# --------- Bravais lattice ----------------------------------
bl = class_( py_type = "BravaisLattice",
c_type = "bravais_lattice",
c_type_absolute = "triqs::lattice::bravais_lattice",
serializable= "tuple",
)
bl.add_constructor(signature = "(matrix<double> units, std::vector<r_t> orbital_positions, std::vector<std::string> atom_orb_name)",
doc = "")
bl.add_constructor(signature = "(matrix<double> units, std::vector<r_t> orbital_positions)",
doc = "")
bl.add_constructor(signature = "(matrix<double> units)",
doc = "")
bl.add_constructor(signature = "()",
doc = "")
bl.add_property(getter = cfunction(c_name="dim", signature = "int()"),
doc = "Dimension of the lattice")
bl.add_property(getter = cfunction(c_name="n_orbitals", signature = "int()"),
doc = "Number of orbitals")
bl.add_property(getter = cfunction(c_name="units", signature = "matrix_const_view<double>()"),
doc = "Base vectors of the lattice")
bl.add_method(py_name = "lattice_to_real_coordinates",
c_name = "lattice_to_real_coordinates",
signature = "r_t(r_t x)",
doc = "Transform into real coordinates.")
module.add_class(bl)
# --------- TightBinding ----------------------------------
tb = class_( py_type = "TightBinding",
c_type = "tight_binding",
c_type_absolute = "triqs::lattice::tight_binding",
#serializable= "tuple",
)
tb.add_constructor(signature = "(bravais_lattice latt, PyObject* hopping)",
calling_pattern =
"""
// We need to rewrite manually the call to the constructor :
// hopping is a dict : displacement -> matrix
// we flatten it into 2 vector of vector and matrix resp.
// for the tight_binding constructor
// First of all, if it is not a dict, error
if (!PyDict_Check(hopping)) {PyErr_SetString(PyExc_TypeError, "hopping must be a mapping type (dict)"); return 0;}
// The arguments for the C++ constructor
std::vector<std::vector<long>> displs;
std::vector<matrix<dcomplex>> mats;
// we loop on the dict // Cf python doc for PyDict_Next
PyObject *key, *value;
Py_ssize_t pos = 0;
while (PyDict_Next(hopping, &pos, &key, &value)) {
displs.push_back(convert_from_python<std::vector<long>>(key));
mats.push_back(convert_from_python<matrix<dcomplex>>(value));
}
auto result = tight_binding(*latt, displs, mats);
""",
doc = " ")
module.add_class(tb)
# --------- Module functions ----------------------------------
module.add_function(name = "hopping_stack",
signature = "array<dcomplex, 3> (tight_binding TB, array_const_view<double, 2> k_stack)",
doc = """ """)
module.add_function(name = "dos",
signature = "std::pair<array<double, 1>, array<double, 2>> (tight_binding TB, int nkpts, int neps)",
doc = """ """)
module.add_function(name = "dos_patch",
signature = "std::pair<array<double, 1>, array<double, 1>> (tight_binding TB, array<double, 2> triangles, int neps, int ndiv)",
doc = """ """)
module.add_function(name = "energies_on_bz_path",
signature = "array<double, 2> (tight_binding TB, k_t K1, k_t K2, int n_pts)",
doc = """ """)
module.add_function(name = "energy_matrix_on_bz_path",
signature = "array<dcomplex, 3> (tight_binding TB, k_t K1, k_t K2, int n_pts)",
doc = """ """)
module.add_function(name = "energies_on_bz_grid",
signature = "array<double, 2> (tight_binding TB, int n_pts)",
doc = """ """)
########################
## Code generation
########################
if __name__ == '__main__' :
module.generate_code(mako_template = sys.argv[1], wrap_file = sys.argv[2])
module.generate_py_converter_header(mako_template = sys.argv[3], wrap_file = sys.argv[4])

View File

@ -0,0 +1,8 @@
SET(PYTHON_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/wrap_generator.py
${CMAKE_CURRENT_SOURCE_DIR}/py_converter_wrapper.mako.hpp
${CMAKE_CURRENT_SOURCE_DIR}/wrapper.mako.cpp
)
install (FILES ${PYTHON_SOURCES} DESTINATION ${CMAKE_INSTALL_PREFIX}/share/triqs/wrap_generator)

View File

@ -57,10 +57,11 @@ class cfunction :
def f(): # analyse the argument, be careful that , can also be in type, like A<B,C>, so we count the < >
acc = ''
for s in args.split(',') :
acc += (',' if acc else '') + s
acc += (',' if acc else '') + s.strip()
if acc.count('<') == acc.count('>') :
r, acc = acc,''
yield r
args = [ re.sub('=',' ',x).split() for x in f() if x] # list of (type, name, default) or (type, name)
else:
self.rtype = kw.pop("rtype", None)
@ -351,12 +352,17 @@ class class_ :
All arguments passed by keywords to function_ construction
"""
assert 'c_name' not in kw, "No c_name here"
assert 'calling_pattern' not in kw, "No calling_pattern here"
f = cfunction(c_name = "__init__", is_constructor = True, **kw)
#assert 'calling_pattern' not in kw, "No calling_pattern here"
if 'calling_pattern' not in kw : kw['c_name'] = "__init__"
f = cfunction(is_constructor = True, **kw)
build_type = regular_type_if_view_else_type(self.c_type) if self.c_type_is_view and build_from_regular_type else self.c_type
all_args = ",".join([ ('*' if t in module_.wrapped_types else '') + n for t,n,d in f.args])
#all_args = ",".join([ ('*' if t in module_.wrapped_types else '') + n + (' = ' + d if d else '') for t,n,d in f.args])
f._calling_pattern = "((%s *)self)->_c ->"%self.py_type + ('operator =' if not self.c_type_is_view else 'rebind') + " (%s (%s));"%(build_type,all_args)
if 'calling_pattern' not in kw :
f._calling_pattern = "((%s *)self)->_c ->"%self.py_type + ('operator =' if not self.c_type_is_view else 'rebind') + " (%s (%s));"%(build_type,all_args)
else :
f._calling_pattern = kw['calling_pattern'] + "\n ((%s *)self)->_c ->"%self.py_type + ('operator =' if not self.c_type_is_view else 'rebind') + " (std::move(result));"
if not self.constructor :
self.constructor = pyfunction(py_name = "__init__", **kw)
self.constructor.is_constructor = True

View File

@ -150,11 +150,18 @@ static PyObject* ${c.py_type}_new(PyTypeObject *type, PyObject *args, PyObject *
${c.py_type} *self;
self = (${c.py_type} *)type->tp_alloc(type, 0);
if (self != NULL) {
try {
%if not c.c_type_is_view :
self->_c = new ${c.c_type}{};
%else :
self->_c = new ${c.c_type}{typename ${c.c_type}::regular_type{}}; // no default constructor for views
%endif
}
catch (std::exception const & e) {
std::cout << e.what()<<std::endl;
PyErr_SetString(PyExc_RuntimeError, "Default constructor of class ${c.py_type} is throwing an exception !");
return NULL;
}
}
return (PyObject *)self;
}

View File

@ -23,7 +23,7 @@
from pytriqs.lattice.tight_binding import *
# Define the Bravais Lattice : a square lattice in 2d
BL = BravaisLattice(units = [(1,0,0) , (0,1,0) ], orbital_positions= {"" : (0,0,0)} )
BL = BravaisLattice(units = [(1,0,0) , (0,1,0) ])
# Prepare a nearest neighbour hopping on BL
t = -1.00 # First neighbour Hopping

View File

@ -44,7 +44,7 @@ namespace lattice {
bravais_lattice(matrix<double> const& units, std::vector<r_t> atom_orb_pos)
: bravais_lattice(units, atom_orb_pos, std::vector<std::string>(atom_orb_pos.size(), "")) {}
bravais_lattice(matrix<double> const& units) : bravais_lattice(units, std::vector<r_t>{{0, 0, 0}}) {}
bravais_lattice() : bravais_lattice(arrays::make_unit_matrix<double>(3)) {}
bravais_lattice() : bravais_lattice(arrays::make_unit_matrix<double>(2)) {}
int n_orbitals() const { return atom_orb_name.size(); }
arrays::matrix_const_view<double> units() const { return units_; }

View File

@ -39,6 +39,8 @@ namespace lattice {
///
tight_binding(bravais_lattice const& bl, std::vector<std::vector<long>> all_disp, std::vector<matrix<dcomplex>> all_matrices);
tight_binding() = default;
/// Underlying lattice
bravais_lattice const& lattice() const { return bl_; }

View File

@ -301,6 +301,38 @@ template <typename T> struct py_converter<std::vector<T>> {
}
};
// --- pair ---
template <typename T1, typename T2> struct py_converter<std::pair<T1,T2>> {
static PyObject * c2py(std::pair<T1,T2> const &p) {
PyObject * list = PyList_New(0);
if (PyList_Append(list, py_converter<T1>::c2py(std::get<0>(p))) == -1) { Py_DECREF(list); return NULL;} // error
if (PyList_Append(list, py_converter<T2>::c2py(std::get<1>(p))) == -1) { Py_DECREF(list); return NULL;} // error
return list;
}
static bool is_convertible(PyObject *ob, bool raise_exception) {
if (!PySequence_Check(ob)) goto _false;
{
pyref seq = PySequence_Fast(ob, "expected a sequence");
if (!py_converter<T1>::is_convertible(PySequence_Fast_GET_ITEM((PyObject*)seq, 0),raise_exception)) goto _false; //borrowed ref
if (!py_converter<T2>::is_convertible(PySequence_Fast_GET_ITEM((PyObject*)seq, 1),raise_exception)) goto _false; //borrowed ref
return true;
}
_false:
if (raise_exception) { PyErr_SetString(PyExc_TypeError, "Can not convert to std::pair");}
return false;
}
static std::pair<T1,T2> py2c(PyObject * ob) {
pyref seq = PySequence_Fast(ob, "expected a sequence");
return std::make_pair(
py_converter<T1>::py2c(PySequence_Fast_GET_ITEM((PyObject*)seq, 0)),
py_converter<T2>::py2c(PySequence_Fast_GET_ITEM((PyObject*)seq, 1))
);
}
};
// --- mini_vector<T,N>---
// via std::vector
template <typename T, int N> struct py_converter<triqs::utility::mini_vector<T,N>> {
@ -339,6 +371,10 @@ template <typename T, int R> struct py_converter<triqs::arrays::array_view<T, R>
template <typename T> struct py_converter<triqs::arrays::matrix_view<T>> : py_converter_array<triqs::arrays::matrix_view<T>> {};
template <typename T> struct py_converter<triqs::arrays::vector_view<T>> : py_converter_array<triqs::arrays::vector_view<T>> {};
template <typename T, int R> struct py_converter<triqs::arrays::array_const_view<T, R>> : py_converter_array<triqs::arrays::array_const_view<T, R>> {};
template <typename T> struct py_converter<triqs::arrays::matrix_const_view<T>> : py_converter_array<triqs::arrays::matrix_const_view<T>> {};
template <typename T> struct py_converter<triqs::arrays::vector_const_view<T>> : py_converter_array<triqs::arrays::vector_const_view<T>> {};
template <typename T, int R> struct py_converter<triqs::arrays::array<T, R>> : py_converter_array<triqs::arrays::array<T, R>> {};
template <typename T> struct py_converter<triqs::arrays::matrix<T>> : py_converter_array<triqs::arrays::matrix<T>> {};
template <typename T> struct py_converter<triqs::arrays::vector<T>> : py_converter_array<triqs::arrays::vector<T>> {};