3
0
mirror of https://github.com/triqs/dft_tools synced 2024-10-31 19:23:45 +01:00

lattice: clean old classes, add bz_mesh, gf on bz

This commit is contained in:
Olivier Parcollet 2014-02-16 13:31:27 +01:00
parent e82d95d1a8
commit 6e87bee850
14 changed files with 803 additions and 494 deletions

View File

@ -10,19 +10,17 @@ from cython.operator cimport dereference as deref, preincrement as inc #derefere
import numpy import numpy
cdef extern from "triqs/lattice/bravais_lattice_and_brillouin_zone.hpp" namespace "triqs::gf" : cdef extern from "triqs/lattice/brillouin_zone.hpp" :
cdef cppclass bravais_lattice_c " triqs::lattice_tools::bravais_lattice" : cdef cppclass bravais_lattice_c " triqs::lattice::bravais_lattice" :
bravais_lattice_c(matrix[double] & units) bravais_lattice_c(matrix[double] & units, vector[tqa_vector[double]] &, vector[std_string] &) except +
int n_orbitals() int n_orbitals()
matrix[double] units() matrix[double] units()
int dim() int dim()
void push_back(std_string &, tqa_vector[double] &)
tqa_vector[double] lattice_to_real_coordinates (tqa_vector_view[double] &) tqa_vector[double] lattice_to_real_coordinates (tqa_vector_view[double] &)
cdef extern from "triqs/lattice/tight_binding.hpp" namespace "triqs::gf" : cdef extern from "triqs/lattice/tight_binding.hpp" namespace "triqs::gf" :
cdef cppclass tight_binding " triqs::lattice_tools::tight_binding" : cdef cppclass tight_binding " triqs::lattice::tight_binding" :
tight_binding(bravais_lattice_c & units) tight_binding(bravais_lattice_c & units, vector[vector[long]] &, vector[matrix[dcomplex]] &) except +
void push_back (vector[long] &, matrix[double] &)
#Fix the name conflict pv wiht a pxd, cf doc....? #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) array_view[complex,THREE] hopping_stack_c "hopping_stack" (tight_binding & TB, array_view[double,TWO] & k_stack)
@ -37,10 +35,13 @@ cdef class BravaisLattice :
cdef bravais_lattice_c * _c cdef bravais_lattice_c * _c
def __init__(self, units, orbital_positions = None ) : def __init__(self, units, orbital_positions = None ) :
""" """ """ """
self._c = new bravais_lattice_c( matrix[double](units)) cdef vector[std_string] names
cdef vector[tqa_vector[double]] atom_pos
orbital_positions = orbital_positions if orbital_positions else dict ("", (0,0,0) ) orbital_positions = orbital_positions if orbital_positions else dict ("", (0,0,0) )
for name, pos in orbital_positions.items(): for name, pos in orbital_positions.items():
self._c.push_back( name, tqa_vector[double](pos)) 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): def __dealloc__(self):
del self._c del self._c
@ -69,11 +70,16 @@ cdef class TightBinding:
cdef tight_binding * _c cdef tight_binding * _c
def __init__(self, BravaisLattice bravais_lattice, hopping ) : def __init__(self, BravaisLattice bravais_lattice, hopping ) :
""" """ """ """
self._c = new tight_binding(deref(bravais_lattice._c)) #self._c = new tight_binding(deref(bravais_lattice._c))
cdef vector[long] d #cdef vector[long] d
cdef vector[matrix[dcomplex]] mats
cdef vector[vector[long]] displs
for displ, mat in hopping.items() : for displ, mat in hopping.items() :
d = displ displs.push_back(displ)
self._c.push_back( d, matrix[double] (numpy.array(mat, dtype =float))) #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): def __dealloc__(self):
del self._c del self._c

36
test/triqs/gfs/g_k_om.cpp Normal file
View File

@ -0,0 +1,36 @@
#define TRIQS_ARRAYS_ENFORCE_BOUNDCHECK
#include <triqs/gfs.hpp>
#include <triqs/gfs/bz.hpp>
using namespace triqs::gfs;
using namespace triqs::clef;
using namespace triqs::arrays;
using namespace triqs::lattice;
#define TEST(X) std::cout << BOOST_PP_STRINGIZE((X)) << " ---> " << (X) << std::endl << std::endl;
int main() {
try {
double beta = 1;
auto bz_ = brillouin_zone{bravais_lattice{make_unit_matrix<double>(2)}};
auto g_eps = gf<bz>{{bz_, 1000}, {1, 1}};
auto G = gf<cartesian_product<bz, imfreq>>{{{bz_, 100}, {beta, Fermion, 100}}, {1, 1}};
// try to assign to expression
placeholder<0> k_;
placeholder<1> w_;
auto eps = make_expr( [](k_t const& k) { return -2 * (cos(k(0)) + cos(k(1))); }) ;
G(k_, w_) << 1 / (w_ - eps(k_) - 1 / (w_ + 2));
// hdf5
H5::H5File file("ess_g_k_om.h5", H5F_ACC_TRUNC );
h5_write(file, "g", G);
}
TRIQS_CATCH_AND_ABORT;
}

75
triqs/gfs/bz.hpp Normal file
View File

@ -0,0 +1,75 @@
/*******************************************************************************
*
* TRIQS: a Toolbox for Research in Interacting Quantum Systems
*
* Copyright (C) 2012-2013 by O. Parcollet
*
* TRIQS is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* TRIQS is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* TRIQS. If not, see <http://www.gnu.org/licenses/>.
*
******************************************************************************/
#pragma once
#include "./tools.hpp"
#include "./gf.hpp"
#include "./local/tail.hpp"
#include "./domains/R.hpp"
#include "../lattice/bz_mesh.hpp"
#include "./evaluators.hpp"
namespace triqs {
namespace gfs {
struct bz {};
template <typename Opt> struct gf_mesh<bz, Opt> : lattice::bz_mesh {
template <typename... T> gf_mesh(T &&... x) : lattice::bz_mesh(std::forward<T>(x)...) {}
};
namespace gfs_implementation {
// h5 name
template <typename Opt> struct h5_name<bz, matrix_valued, Opt> {
static std::string invoke() { return "BZ"; }
};
/// --------------------------- data access ---------------------------------
template <typename Opt> struct data_proxy<bz, matrix_valued, Opt> : data_proxy_array<std::complex<double>, 3> {};
template <typename Opt> struct data_proxy<bz, scalar_valued, Opt> : data_proxy_array<std::complex<double>, 1> {};
/// --------------------------- evaluator ---------------------------------
// simple evaluation : take the point on the grid...
template <> struct evaluator_fnt_on_mesh<bz> {
lattice::k_t k;
evaluator_fnt_on_mesh() = default;
template <typename MeshType> evaluator_fnt_on_mesh(MeshType const &m, lattice::k_t const &k_) { k = k_; }
template <typename F> auto operator()(F const &f) const DECL_AND_RETURN(f(k));
};
// ------------- evaluator -------------------
// handle the case where the matsu. freq is out of grid...
template <typename Target, typename Opt> struct evaluator<bz, Target, Opt> {
static constexpr int arity = 1;
template <typename G>
std::c14::conditional_t<std::is_same<Target, matrix_valued>::value, arrays::matrix_const_view<std::complex<double>>,
std::complex<double>>
operator()(G const *g, lattice::k_t const &k) const {
auto n = g->mesh().locate_neighbours(k); // TO BE IMPROVED
return (*g)[n];
}
};
}
}
}

View File

@ -0,0 +1,82 @@
/*******************************************************************************
*
* TRIQS: a Toolbox for Research in Interacting Quantum Systems
*
* Copyright (C) 2011-2014 by M. Ferrero, O. Parcollet
*
* TRIQS is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* TRIQS is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* TRIQS. If not, see <http://www.gnu.org/licenses/>.
*
******************************************************************************/
#pragma once
#include <triqs/arrays.hpp>
#include <string>
#include <vector>
namespace triqs {
namespace lattice {
using r_t = arrays::vector<double>;
using k_t = arrays::vector<double>;
using dcomplex = std::complex<double>;
using arrays::matrix;
using arrays::array;
using arrays::range;
// --------------------------------------------------------
class bravais_lattice {
public:
using point_t = std::vector<int>; // domain concept. PUT on STACK
bravais_lattice(matrix<double> const& units, std::vector<r_t> atom_orb_pos, std::vector<std::string> atom_orb_name);
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)) {}
int n_orbitals() const { return atom_orb_name.size(); }
arrays::matrix_const_view<double> units() const { return units_; }
int dim() const { return dim_; }
/// Transform into real coordinates.
template <typename R> r_t lattice_to_real_coordinates(R const& x) const {
r_t res(3);
res() = 0;
for (int i = 0; i < dim_; i++) res += x(i) * units_(i, range{});
return res;
}
/// Write into HDF5
friend void h5_write(h5::group fg, std::string subgroup_name, bravais_lattice const& bl);
/// Read from HDF5
friend void h5_read(h5::group fg, std::string subgroup_name, bravais_lattice& bl);
// BOOST Serialization
friend class boost::serialization::access;
template <class Archive> void serialize(Archive& ar, const unsigned int version) {
ar& boost::serialization::make_nvp("units", units_);
ar& boost::serialization::make_nvp("atom_orb_pos", atom_orb_pos);
ar& boost::serialization::make_nvp("atom_orb_name", atom_orb_name);
}
private:
matrix<double> units_;
std::vector<r_t> atom_orb_pos; // atom_orb_pos[i] = position of ith atoms/orbitals in the unit cell
std::vector<std::string> atom_orb_name; // names of these atoms/orbitals.
int dim_;
};
}
}

View File

@ -18,79 +18,106 @@
* TRIQS. If not, see <http://www.gnu.org/licenses/>. * TRIQS. If not, see <http://www.gnu.org/licenses/>.
* *
******************************************************************************/ ******************************************************************************/
#include "bravais_lattice_and_brillouin_zone.hpp" #include "./bravais_lattice.hpp"
#include "./brillouin_zone.hpp"
#include <triqs/arrays/blas_lapack/dot.hpp> #include <triqs/arrays/blas_lapack/dot.hpp>
#include <triqs/arrays/linalg/det_and_inverse.hpp> #include <triqs/arrays/linalg/det_and_inverse.hpp>
#include <triqs/arrays/linalg/cross_product.hpp> #include <triqs/arrays/linalg/cross_product.hpp>
namespace triqs { namespace lattice_tools { namespace triqs {
namespace lattice {
using namespace tqa; const double almost_zero = 1e-10;
using namespace std;
//using triqs::arrays::blas::dot;
const double almost_zero(1E-10);
bravais_lattice::bravais_lattice( units_type const & units__) : units_(3,3), dim_(units__.shape(0)) { bravais_lattice::bravais_lattice(matrix<double> const& units__, std::vector<r_t> atom_orb_pos_,
units_(range(0,dim_),range()) = units__(); std::vector<std::string> atom_orb_name_)
units_(range(dim_,3),range()) = 0; : units_(3, 3), atom_orb_pos(atom_orb_pos_), atom_orb_name(atom_orb_name_) {
dim_ = first_dim(units__);
if ((dim_ < 1) || (dim_ > 3)) TRIQS_RUNTIME_ERROR << " units matrix must be square matrix of size 1, 2 or 3";
using arrays::range;
auto r = range(0, dim_);
units_() = 0;
units_(r, r) = units__(r, r);
// First complete the basis. Add some tests for safety // First complete the basis. Add some tests for safety
tqa::vector<double> ux(3),uy(3),uz(3); arrays::vector<double> ux(3), uy(3), uz(3);
assert(dim_==2); double delta;
auto _ = range{};
switch (dim_) { switch (dim_) {
case 1: case 1:
ux = units_(0,range()); ux = units_(0, _);
uz() = 0; uz(1) = 1 ; uz() = 0;
uz = uz - dot(uz,ux)* ux; uz(1) = 1;
uz = uz - dot(uz, ux) * ux;
// no luck, ux was parallel to z, another one must work // no luck, ux was parallel to z, another one must work
if (sqrt(dot(uz,uz))<almost_zero) { if (sqrt(dot(uz, uz)) < almost_zero) {
uz() = 0; uz(2) = 1; // 0,0,1; uz() = 0;
uz = uz - dot(uz,ux)* ux; uz(2) = 1; // 0,0,1;
uz = uz - dot(uz, ux) * ux;
} }
uz /= sqrt(dot(uz,uz)); uz /= sqrt(dot(uz, uz));
uy = cross_product(uz,ux); uy = cross_product(uz, ux);
uy = uy/sqrt(dot(uy,uy)); // uy can not be 0 uy = uy / sqrt(dot(uy, uy)); // uy can not be 0
units_(1,range()) = uz; units_(1, _) = uz;
units_(2,range()) = uy; units_(2, _) = uy;
break; break;
case 2: case 2:
uy() = 0; uy(2) = 1 ; uy() = 0;
uy = cross_product(units_(0,range()),units_(1,range())); uy(2) = 1;
double delta = sqrt(dot(uy,uy)); uy = cross_product(units_(0, _), units_(1, _));
if (abs(delta)<almost_zero) TRIQS_RUNTIME_ERROR<<"Tiling : the 2 vectors of unit are not independent"; delta = sqrt(dot(uy, uy));
units_(2,range()) = uy /delta; if (abs(delta) < almost_zero) TRIQS_RUNTIME_ERROR << "Bravais Lattice : the 2 vectors of unit are not independent : " << units__;
units_(2, _) = uy / delta;
break;
case 3:
TRIQS_RUNTIME_ERROR << " 3d bravais lattice not implemented";
break;
} }
//cerr<<" Units = "<< units_<<endl; }
//------------------------------------------------------------------------------------
/// Write into HDF5
void h5_write(h5::group fg, std::string subgroup_name, bravais_lattice const& bl) {
h5::group gr = fg.create_group(subgroup_name);
h5_write(gr, "units", bl.units_); // NOT COMPLETE
}
/// Read from HDF5
void h5_read(h5::group fg, std::string subgroup_name, bravais_lattice& bl) {
h5::group gr = fg.open_group(subgroup_name);
matrix<double> u;
h5_read(gr, "units", u);
bl = bravais_lattice{u}; // NOT COMPLETE
} }
//------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
brillouin_zone::brillouin_zone( bravais_lattice const & bl_) : lattice_(bl_), K_reciprocal(3,3) { brillouin_zone::brillouin_zone(bravais_lattice const& bl_) : lattice_(bl_), K_reciprocal(3, 3) {
bravais_lattice::units_type Units(lattice().units()); using arrays::range;
std::cout << Units << std::endl; auto _ = range{};
double delta = dot(Units(0,range()), cross_product(Units(1,range()),Units(2,range()))); auto Units = lattice().units();
std::cout << dot(Units(0,range()), cross_product(Units(1,range()),Units(2,range())))<<std::endl; double delta = dot(Units(0, _), cross_product(Units(1, _), Units(2, _)));
std::cout << cross_product(Units(1,range()),Units(2,range()))<<std::endl; if (abs(delta) < almost_zero) TRIQS_RUNTIME_ERROR << "Brillouin Zone : the 3 vectors of Units are not independant" << Units;
if (abs(delta)<almost_zero) TRIQS_RUNTIME_ERROR<<"Tiling : the 3 vectors of Units are not independant"; K_reciprocal(0, _) = cross_product(Units(1, _), Units(2, _)) / delta;
K_reciprocal(0,range()) = cross_product(Units(1,range()),Units(2,range())) / delta; K_reciprocal(1, _) = cross_product(Units(2, _), Units(0, _)) / delta;
K_reciprocal(1,range()) = cross_product(Units(2,range()),Units(0,range())) / delta; K_reciprocal(2, _) = cross_product(Units(0, _), Units(1, _)) / delta;
K_reciprocal(2,range()) = cross_product(Units(0,range()),Units(1,range())) / delta; K_reciprocal = K_reciprocal * 2 * M_PI;
//for (size_t i =0; i< lattice().dim();i++) std::cerr << " K_reciprocal(" << i << ")/(2pi) = " << K_reciprocal(i,range())<< std::endl; K_reciprocal_inv = inverse(K_reciprocal);
const double pi = acos(-1.0);
K_reciprocal = K_reciprocal*2*pi;
K_reciprocal_inv = inverse(K_reciprocal);
} }
K_view_type brillouin_zone::lattice_to_real_coordinates (K_view_type const & k) const { //------------------------------------------------------------------------------------
if (k.size()!=lattice().dim()) TRIQS_RUNTIME_ERROR<<"latt_to_real_k : dimension of k must be "<<lattice().dim(); /// Write into HDF5
K_type res(3); res()=0; int dim = lattice().dim(); void h5_write(h5::group fg, std::string subgroup_name, brillouin_zone const& bz) {
for (int i =0; i< dim;i++) res += k (i) * K_reciprocal(i,range()); h5::group gr = fg.create_group(subgroup_name);
return(res); h5_write(gr, "bravais_lattice", bz.lattice_);
} }
K_view_type brillouin_zone::real_to_lattice_coordinates (K_view_type const & k) const { /// Read from HDF5
if (k.size()!=lattice().dim()) TRIQS_RUNTIME_ERROR<<"latt_to_real_k : dimension of k must be "<<lattice().dim(); void h5_read(h5::group fg, std::string subgroup_name, brillouin_zone& bz) {
K_type res(3);res()=0; int dim = lattice().dim(); h5::group gr = fg.open_group(subgroup_name);
for (int i =0; i< dim;i++) res += k (i) * K_reciprocal_inv(i,range()); bravais_lattice bl;
return(res); h5_read(gr, "bravais_lattice", bl);
bz = brillouin_zone{bl};
} }
}}//namespaces }
} // namespaces

View File

@ -1,99 +0,0 @@
/*******************************************************************************
*
* TRIQS: a Toolbox for Research in Interacting Quantum Systems
*
* Copyright (C) 2011 by M. Ferrero, O. Parcollet
*
* TRIQS is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* TRIQS is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* TRIQS. If not, see <http://www.gnu.org/licenses/>.
*
******************************************************************************/
#ifndef TRIQS_LATTICE_BRAVAIS_LATTICE_H
#define TRIQS_LATTICE_BRAVAIS_LATTICE_H
#include <triqs/arrays/array.hpp>
#include <triqs/arrays/matrix.hpp>
#include <triqs/arrays/vector.hpp>
#include <triqs/utility/exceptions.hpp>
#include <unordered_map>
#include <map>
#include <string>
#include <unordered_map>
namespace triqs { namespace lattice_tools {
namespace tqa = triqs::arrays;
using tqa::array; using tqa::array_view; using tqa::matrix_view;using tqa::matrix;using tqa::range;
typedef tqa::vector <double> R_type;
typedef tqa::vector <double> K_type;
typedef tqa::vector_view<double> R_view_type;
typedef tqa::vector_view<double> K_view_type;
typedef std::complex<double> dcomplex;
class bravais_lattice {
public :
typedef matrix<double> units_type;
typedef std::unordered_map<std::string, R_type> orbital_type; // name -> position in space
bravais_lattice(units_type const & units);
size_t n_orbitals() const {return orbitals_.size();}
units_type const & units() const { return units_;}
size_t dim() const { return dim_; }
/**
* Push_back mechanism of a pair orbital_name -> position in R^3
* VectorType is anything from which a tqa::vector <double> can be constructed
*/
template<typename VectorType>
void push_back(std::string const & s, VectorType && v) { orbitals_.insert(std::make_pair(s,std::forward<VectorType>(v)));}
/***
* Transform into real coordinates.
* @param[in] x : coordinates in the basis :unit_i arrays::vector or vector_view
* @return Coordinates in R^3 ("real" coordinates)
*/
template<typename R>
R_view_type lattice_to_real_coordinates(R const & x) const {
R_type res(3); res() =0;
for (size_t i =0; i< dim();i++) res += x (i) * units_(i,range());
return(res);
}
protected :
units_type units_;
size_t dim_;
orbital_type orbitals_;
};
class brillouin_zone {
bravais_lattice lattice_;
tqa::matrix<double> K_reciprocal, K_reciprocal_inv;
public :
brillouin_zone( bravais_lattice const & bl_);
bravais_lattice lattice() const { return lattice_;}
/***
* Transform into real coordinates.
* @param[in] k : coordinates in the basis (K_reciprocal_i)
* @return Coordinates in R^3 ("real" coordinates)
*/
K_view_type lattice_to_real_coordinates (K_view_type const & k) const;
/// Inverse of latt_to_real_k
K_view_type real_to_lattice_coordinates (K_view_type const & k) const;
};
}}
#endif

View File

@ -0,0 +1,75 @@
/*******************************************************************************
*
* TRIQS: a Toolbox for Research in Interacting Quantum Systems
*
* Copyright (C) 2011-2014 by M. Ferrero, O. Parcollet
*
* TRIQS is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* TRIQS is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* TRIQS. If not, see <http://www.gnu.org/licenses/>.
*
******************************************************************************/
#pragma once
#include "./bravais_lattice.hpp"
namespace triqs {
namespace lattice {
class brillouin_zone {
public:
using point_t = k_t; // domain concept
brillouin_zone() { // default construction, 3d cubic lattice
K_reciprocal = arrays::make_unit_matrix<double>(3);
K_reciprocal_inv() = K_reciprocal;
}
/// Construct from a bravais_lattice
brillouin_zone(bravais_lattice const& bl_);
/// Access to the underlying bravais lattice
bravais_lattice lattice() const { return lattice_; }
/// Transform from lattice to real coordinates
template <typename K> k_t lattice_to_real_coordinates(K const& k) const { return _transfo_impl(k, K_reciprocal); }
/// Transform from real to lattice coordinates
template <typename K> k_t real_to_lattice_coordinates(K const& k) const { return _transfo_impl(k, K_reciprocal_inv); }
/// Write into HDF5
friend void h5_write(h5::group fg, std::string subgroup_name, brillouin_zone const& bz);
/// Read from HDF5
friend void h5_read(h5::group fg, std::string subgroup_name, brillouin_zone& bz);
// BOOST Serialization
friend class boost::serialization::access;
template <class Archive> void serialize(Archive& ar, const unsigned int version) {
ar& boost::serialization::make_nvp("bravais_lattice", lattice_);
}
private:
bravais_lattice lattice_;
arrays::matrix<double> K_reciprocal, K_reciprocal_inv;
template <typename K> k_t _transfo_impl(K const& k, arrays::matrix<double> const& K_base) const {
if (first_dim(k) != lattice().dim()) TRIQS_RUNTIME_ERROR << "latt_to_real_k : dimension of k must be " << lattice().dim();
k_t res(3);
res() = 0;
int dim = lattice().dim();
for (int i = 0; i < dim; i++) res += k(i) * K_reciprocal_inv(i, range{});
return res;
}
};
}
}

75
triqs/lattice/bz_mesh.cpp Normal file
View File

@ -0,0 +1,75 @@
/*******************************************************************************
*
* TRIQS: a Toolbox for Research in Interacting Quantum Systems
*
* Copyright (C) 2011 by M. Ferrero, O. Parcollet
*
* TRIQS is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* TRIQS is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* TRIQS. If not, see <http://www.gnu.org/licenses/>.
*
******************************************************************************/
#include "./bz_mesh.hpp"
#include "./grid_generator.hpp"
namespace triqs {
namespace lattice {
bz_mesh::bz_mesh(brillouin_zone const &bz, int n_l) : bz(bz) {
// compute the k points
for (auto grid = grid_generator{bz.lattice().dim(), n_l}; grid; ++grid) k_pt_stack.push_back(*grid);
}
// locate the closest point : VERY PRIMITIVE : TO BE IMPROVED (kd-tree ?)
long bz_mesh::locate_neighbours(k_t k) const {
// reduction to the BZ ?
// very slow : improve with a kd-tree ?
double d_min = 100; // > pi
auto sqr = [](double x) { return x * x; };
int pos = 0, pos_min = 0;
for (auto const &p : k_pt_stack) {
int dim = k.size();
double d = 0;
for (int i = 0; i < dim; ++i) d += sqr(k(i) - p(i));
if (d < d_min) {
d_min = d;
pos_min = pos;
}
pos++;
}
return pos;
}
/// Write into HDF5
void h5_write(h5::group fg, std::string subgroup_name, bz_mesh const &m) {
h5::group gr = fg.create_group(subgroup_name);
h5_write(gr, "domain", m.domain());
auto kp = matrix<double>(m.k_pt_stack.size(), 3);
kp() = 0;
for (int i = 0; i < m.k_pt_stack.size(); ++i) kp(i, range{}) = m.k_pt_stack[i];
h5_write(gr, "k_pt_stack", kp);
}
/// Read from HDF5
void h5_read(h5::group fg, std::string subgroup_name, bz_mesh &m) {
h5::group gr = fg.open_group(subgroup_name);
brillouin_zone dom;
h5_read(gr, "domain", dom);
matrix<double> kp;
h5_read(gr, "k_pt_stack", kp);
std::vector<k_t> k_pt_stack;
int s = first_dim(kp);
for (int i = 0; i < s; ++i) k_pt_stack[i] = kp(i, range{});
m = bz_mesh(std::move(dom), k_pt_stack);
}
}
} // namespaces

109
triqs/lattice/bz_mesh.hpp Normal file
View File

@ -0,0 +1,109 @@
/*******************************************************************************
*
* TRIQS: a Toolbox for Research in Interacting Quantum Systems
*
* Copyright (C) 2012 by M. Ferrero, O. Parcollet
*
* TRIQS is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* TRIQS is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* TRIQS. If not, see <http://www.gnu.org/licenses/>.
*
******************************************************************************/
#pragma once
#include "./brillouin_zone.hpp"
#include "../gfs/tools.hpp"
#include "../gfs/meshes/mesh_tools.hpp"
namespace triqs {
namespace lattice {
struct bz_mesh {
using domain_t = brillouin_zone;
using index_t = long;
using domain_pt_t = typename domain_t::point_t;
bz_mesh() = default;
bz_mesh(brillouin_zone const &bz, int n_l);
bz_mesh(brillouin_zone const &bz, std::vector<k_t> k_pt_stack) : bz(bz), k_pt_stack(std::move(k_pt_stack)) {}
domain_t const &domain() const { return bz; }
long size() const { return k_pt_stack.size(); }
/// Conversions point <-> index <-> linear_index
domain_pt_t const &index_to_point(index_t i) const { return k_pt_stack[i]; }
long index_to_linear(index_t ind) const { return ind; }
// f (k) -> void where k is a k_t, a point in the BZ
template <typename F> friend void foreach(bz_mesh const &m, F f) {
for (auto const &k : m.k_pt_stack) f(k);
}
// locate the closest point : VERY PRIMITIVE : TO BE IMPROVED (kd-tree ?)
long locate_neighbours(k_t k) const;
/// The wrapper for the mesh point
class mesh_point_t : gfs::tag::mesh_point, public utility::arithmetic_ops_by_cast<mesh_point_t, domain_pt_t> {
bz_mesh const *m;
index_t _index;
public:
mesh_point_t() : m(nullptr) {}
mesh_point_t(bz_mesh const &mesh, index_t const &index_) : m(&mesh), _index(index_) {}
mesh_point_t(bz_mesh const &mesh) : mesh_point_t(mesh, 0) {}
void advance() { ++_index; }
using cast_t = domain_pt_t;
operator cast_t() const { return m->index_to_point(_index); }
long linear_index() const { return _index; }
long index() const { return _index; }
bool at_end() const { return (_index == m->size()); }
void reset() { _index = 0; }
};
/// Accessing a point of the mesh
mesh_point_t operator[](index_t i) const { return mesh_point_t(*this, i); }
/// Iterating on all the points...
using const_iterator = gfs::mesh_pt_generator<bz_mesh>;
const_iterator begin() const { return const_iterator(this); }
const_iterator end() const { return const_iterator(this, true); }
const_iterator cbegin() const { return const_iterator(this); }
const_iterator cend() const { return const_iterator(this, true); }
/// Mesh comparison
bool operator==(bz_mesh const &M) const { return ( (size() == M.size())); }
//bool operator==(bz_mesh const &M) const { return ((bz == M.bz) && (size() == M.size())); }
bool operator!=(bz_mesh const &M) const { return !(operator==(M)); }
/// Write into HDF5
friend void h5_write(h5::group fg, std::string subgroup_name, bz_mesh const &m);
/// Read from HDF5
friend void h5_read(h5::group fg, std::string subgroup_name, bz_mesh &m);
// BOOST Serialization
friend class boost::serialization::access;
template <class Archive> void serialize(Archive &ar, const unsigned int version) {
ar &boost::serialization::make_nvp("domain", bz);
ar &boost::serialization::make_nvp("k_pt_stack", k_pt_stack);
}
friend std::ostream &operator<<(std::ostream &sout, bz_mesh const &m) { return sout << "Mesh over BZ "; }
private:
domain_t bz;
std::vector<k_t> k_pt_stack;
};
}
}

View File

@ -1,28 +0,0 @@
Concept Function
return_type
arg_type
return_type operator()(arg_type const &) const : the evaluation of the function
Concept FunctionOnBravaisLattice
refines Function
bravais_lattice const & lattice() const
Concept ShortRangeFunctionOnBravaisLattice
* refines FunctionOnBravaisLattice
* derived from Tag::ShortRangeFunctionOnBravaisLattice ??
* map_type
* begin, end: iterator -> pair<arg_type, return_type>
Concept FunctionOnBrillouinZone
* refines Function
brillouin_zone const & bz() const

View File

@ -1,90 +0,0 @@
/*******************************************************************************
*
* TRIQS: a Toolbox for Research in Interacting Quantum Systems
*
* Copyright (C) 2011 by M. Ferrero, O. Parcollet
*
* TRIQS is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* TRIQS is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* TRIQS. If not, see <http://www.gnu.org/licenses/>.
*
******************************************************************************/
#ifndef TRIQS_LATTICE_FUNCTORS_H
#define TRIQS_LATTICE_FUNCTORS_H
namespace triqs { namespace lattice_tools {
const double pi = acos(-1.0);
const std::complex<double> I(0,1);
template<typename F> struct minus_chech_impl {
typedef typename F::arg_type arg_type;
typedef typename F::return_type return_type;
F f;
minus_chech_impl(F const & f_):f(f_){}
brillouin_zone const & bz() const {return f.bz();}
return_type operator()(arg_type const & x) const { return_type res(f(x)); res *=-1; return res;}
};
namespace result_of { template<typename F> struct minus_chech{ typedef minus_chech_impl<F> type;}; }
/**
* Given f of type F which models FunctionOnBravaisLattice, minus_check(f) :
* - returns -f(-args)
* - its type models Function
*
*/
template<typename F> minus_chech_impl<F> minus_chech(F const & f) { return minus_chech_impl<F> (f);}
template<typename F >//, typename Enabler = boost::enable_if< Tag::check<Tag::ShortRangeFunctionOnBravaisLattice, F> > >
class fourier_impl {
F f;
brillouin_zone bz_;
// deduce the return type from decltype(begin()->second)
public:
typedef typename regular_type_if_exists_else_type< decltype(f.begin()->second)>::type return_construct_type;
typedef typename view_type_if_exists_else_type<return_construct_type>::type return_type;
typedef K_view_type arg_type;
fourier_impl (F f_):f(f_), bz_(f_.lattice()), res(f.n_bands(),f.n_bands()) {}
//brillouin_zone const & bz() const { return bz_; }
return_type operator()(K_view_type const & k) {
res()=0;
for (auto const & pdm : f) { res += pdm.second * exp( 2*pi*I* this->dot_product(k,pdm.first)); }
return res;
}
protected:
inline double dot_product(K_view_type const & a, typename F::arg_type const & b) const {
assert(b.size()>= this->bz_.lattice().dim());
double r=0; for (size_t i=0; i< this->bz_.lattice().dim();++i) r += a(i) * b[i];
return r;
}
return_construct_type res;
//typename F::return_construct_type res;
};
/**
* Given f of type F which models ShortRangeFunctionOnBravaisLattice, Fourier(f) returns
* - a type that models FunctionOnBravaisLattice
* - and returns the Fourier transform f(k)
*/
template<typename F> fourier_impl<F> Fourier(F f) { return fourier_impl<F> (f);}
//namespace result_of { template<typename F> struct Fourier { typedef fourier_impl<F> type;}; }
}}
#endif

View File

@ -1,4 +1,3 @@
/******************************************************************************* /*******************************************************************************
* *
* TRIQS: a Toolbox for Research in Interacting Quantum Systems * TRIQS: a Toolbox for Research in Interacting Quantum Systems
@ -19,55 +18,77 @@
* TRIQS. If not, see <http://www.gnu.org/licenses/>. * TRIQS. If not, see <http://www.gnu.org/licenses/>.
* *
******************************************************************************/ ******************************************************************************/
#pragma once
#include "./brillouin_zone.hpp"
#ifndef TRIQS_GRID_GENERATOR_H namespace triqs {
#define TRIQS_GRID_GENERATOR_H namespace lattice {
#include <triqs/arrays/array.hpp>
namespace triqs { namespace lattice_tools {
/** /**
* Generate the point in a cuboid as an array<double,1> const & * Generate the point in a cuboid as an array<double,1> const &
*/ */
class grid_generator : class grid_generator : public boost::iterator_facade<grid_generator, k_t const &, boost::forward_traversal_tag, k_t const &> {
public boost::iterator_facade< grid_generator, K_type const &, boost::forward_traversal_tag, K_type const & > { friend class boost::iterator_core_access;
friend class boost::iterator_core_access; int dim, nkpts, nx, ny, nz, N_X, N_Y, N_Z, index_;
size_t dim, nkpts,nx,ny,nz,N_X,N_Y,N_Z,index_; double step_x, step_y, step_z;
double step_x, step_y, step_z; bool at_end;
bool at_end; k_t pt;
K_type pt; void init() {
void init() { nx = 0;
nx=0; ny=0; nz=0;at_end = false;index_ =0; ny = 0;
N_X = nkpts; nz = 0;
N_Y = (dim>1 ? nkpts : 1); at_end = false;
N_Z = (dim>2 ? nkpts : 1); index_ = 0;
step_x = 1.0/double(N_X); step_y = 1.0/double(N_Y); step_z = 1.0/double(N_Z); N_X = nkpts;
pt(0)=step_x/2; pt(1)=step_y/2; pt(2)=step_z/2; N_Y = (dim > 1 ? nkpts : 1);
N_Z = (dim > 2 ? nkpts : 1);
step_x = 1.0 / double(N_X);
step_y = 1.0 / double(N_Y);
step_z = 1.0 / double(N_Z);
pt(0) = step_x / 2;
pt(1) = step_y / 2;
pt(2) = step_z / 2;
}
void increment() {
if (nx < N_X - 1) {
++nx;
pt(0) += step_x;
++index_;
return;
} }
pt(0) = step_x / 2;
void increment() { nx = 0;
if (nx<N_X-1) { ++nx; pt(0) += step_x; ++index_; return;} if (ny < N_Y - 1) {
pt(0) = step_x/2; nx = 0; ++ny;
if (ny<N_Y-1) { ++ny; pt(1) += step_y; ++index_; return;} pt(1) += step_y;
pt(1) = step_y/2; ny = 0; ++index_;
if (nz<N_Z-1) { ++nz; pt(2) += step_z; ++index_; return;} return;
at_end = true;
} }
pt(1) = step_y / 2;
ny = 0;
if (nz < N_Z - 1) {
++nz;
pt(2) += step_z;
++index_;
return;
}
at_end = true;
}
value_type dereference() const { return pt;} value_type dereference() const { return pt; }
bool equal(grid_generator const & other) const { return ((other.dim == dim) && (other.index_==index_) && (other.nkpts==nkpts));} bool equal(grid_generator const &other) const {
return ((other.dim == dim) && (other.index_ == index_) && (other.nkpts == nkpts));
public: }
/// dim : dimension, nkpts : number of k point in each dimension
grid_generator(size_t dim_, size_t nkpts_): dim(dim_),nkpts(nkpts_), pt(3) {init();}
grid_generator():dim(3), nkpts(0), pt(3) {init();}
size_t size () const { return (N_X * N_Y * N_Z);}
size_t index() const { return index_;}
operator bool() const { return !(at_end);}
};
}}
#endif
public:
/// dim : dimension, nkpts : number of k point in each dimension
grid_generator(int dim_, int nkpts_) : dim(dim_), nkpts(nkpts_), pt(3) { init(); }
grid_generator() : dim(3), nkpts(0), pt(3) { init(); }
int size() const { return (N_X * N_Y * N_Z); }
int index() const { return index_; }
operator bool() const { return !(at_end); }
};
}
}

View File

@ -22,170 +22,186 @@
#include <triqs/arrays/algorithms.hpp> #include <triqs/arrays/algorithms.hpp>
#include <triqs/arrays/linalg/eigenelements.hpp> #include <triqs/arrays/linalg/eigenelements.hpp>
#include "grid_generator.hpp" #include "grid_generator.hpp"
#include "functors.hpp" namespace triqs {
namespace triqs { namespace lattice_tools { namespace lattice {
using namespace std;
using namespace tqa; using namespace arrays;
tight_binding::tight_binding(bravais_lattice const& bl, std::vector<std::vector<long>> all_disp,
std::vector<matrix<dcomplex>> all_matrices)
: bl_(bl), all_disp(std::move(all_disp)), all_matrices(std::move(all_matrices)) {
// checking inputs
if (all_disp.size() != all_matrices.size()) TRIQS_RUNTIME_ERROR << " Number of displacements != Number of matrices";
for (int i = 0; i < all_disp.size(); ++i) {
if (all_disp[i].size() != bl_.dim())
TRIQS_RUNTIME_ERROR << "displacement of incorrect size : got " << all_disp[i].size() << "instead of " << bl_.dim();
if (first_dim(all_matrices[i]) != n_bands())
TRIQS_RUNTIME_ERROR << "the first dim matrix is of size " << first_dim(all_matrices[i]) << " instead of " << n_bands();
if (second_dim(all_matrices[i]) != n_bands())
TRIQS_RUNTIME_ERROR << "the second dim matrix is of size " << second_dim(all_matrices[i]) << " instead of " << n_bands();
}
}
//------------------------------------------------------ //------------------------------------------------------
array<dcomplex, 3> hopping_stack(tight_binding const& TB, arrays::array_const_view<double, 2> k_stack) {
array_view <dcomplex,3> hopping_stack (tight_binding const & TB, array_view<double,2> const & k_stack) { auto TK = fourier(TB);
auto TK = Fourier(TB); array<dcomplex, 3> res(TB.n_bands(), TB.n_bands(), k_stack.shape(1));
array<dcomplex,3> res(TB.n_bands(), TB.n_bands(), k_stack.shape(1)); for (int i = 0; i < k_stack.shape(1); ++i) res(range(), range(), i) = TK(k_stack(range(), i));
for(size_t i = 0; i<k_stack.shape(1); ++i) res(range(), range(), i) = TK(k_stack(range(),i));
return res; return res;
} }
//------------------------------------------------------ //------------------------------------------------------
array<double, 2> energies_on_bz_path(tight_binding const& TB, k_t const& K1, k_t const& K2, int n_pts) {
array_view<double,2> energies_on_bz_path(tight_binding const & TB, K_view_type K1, K_view_type K2, size_t n_pts) { auto TK = fourier(TB);
auto TK = Fourier(TB); int norb = TB.lattice().n_orbitals();
const size_t norb=TB.lattice().n_orbitals(); int ndim = TB.lattice().dim();
const size_t ndim=TB.lattice().dim(); array<double, 2> eval(norb, n_pts);
array<double,2> eval(norb,n_pts); k_t dk = (K2 - K1) / double(n_pts), k = K1;
K_type dk = (K2 - K1)/double(n_pts), k = K1; for (int i = 0; i < n_pts; ++i, k += dk) {
for (size_t i =0; i<n_pts; ++i, k += dk) { eval(range(), i) = linalg::eigenvalues(TK(k(range(0, ndim)))(), false);
eval(range(),i) = linalg::eigenvalues( TK( k (range(0,ndim))), false);
} }
return eval; return eval;
} }
//------------------------------------------------------ //------------------------------------------------------
array_view<double,2> energies_on_bz_grid(tight_binding const & TB, size_t n_pts) { array<double, 2> energies_on_bz_grid(tight_binding const& TB, int n_pts) {
auto TK = Fourier(TB); auto TK = fourier(TB);
const size_t norb=TB.lattice().n_orbitals(); int norb = TB.lattice().n_orbitals();
const size_t ndim=TB.lattice().dim(); int ndim = TB.lattice().dim();
grid_generator grid(ndim,n_pts); grid_generator grid(ndim, n_pts);
array<double,2> eval(norb,grid.size()); array<double, 2> eval(norb, grid.size());
for (; grid ; ++grid) { for (; grid; ++grid) {
eval(range(),grid.index()) = linalg::eigenvalues( TK( (*grid) (range(0,ndim))), false); eval(range(), grid.index()) = linalg::eigenvalues(TK((*grid)(range(0, ndim)))(), false);
} }
return eval; return eval;
} }
//------------------------------------------------------ //------------------------------------------------------
std::pair<array<double,1>, array<double,2> > dos(tight_binding const & TB, size_t nkpts, size_t neps) { std::pair<array<double, 1>, array<double, 2>> dos(tight_binding const& TB, int nkpts, int neps) {
// The Fourier transform of TK // The fourier transform of TK
// auto TK = Fourier(TB); // C++0x .... auto TK = fourier(TB);
auto TK = Fourier(TB);
// loop on the BZ // loop on the BZ
const size_t ndim=TB.lattice().dim(); int ndim = TB.lattice().dim();
const size_t norb=TB.lattice().n_orbitals(); int norb = TB.lattice().n_orbitals();
grid_generator grid(ndim,nkpts); grid_generator grid(ndim, nkpts);
array<double,1> tempeval(norb); array<double, 1> tempeval(norb);
array<dcomplex,3> evec(norb,norb,grid.size()); array<dcomplex, 3> evec(norb, norb, grid.size());
array<double,2> eval(norb,grid.size()); array<double, 2> eval(norb, grid.size());
if (norb ==1) if (norb == 1)
for (; grid ; ++grid) { for (; grid; ++grid) {
double ee = real(TK( (*grid) (range(0,ndim)))(0,0)); double ee = real(TK((*grid)(range(0, ndim)))(0, 0));
eval(0,grid.index()) =ee; eval(0, grid.index()) = ee;
evec(0,0,grid.index()) =1; evec(0, 0, grid.index()) = 1;
} }
else else
for (; grid ; ++grid) { for (; grid; ++grid) {
//cerr<<" index = "<<grid.index()<<endl; // cerr<<" index = "<<grid.index()<<endl;
array_view <double,1> eval_sl = eval(range(),grid.index()); array_view<double, 1> eval_sl = eval(range(), grid.index());
array_view <dcomplex,2> evec_sl = evec(range(),range(),grid.index()); array_view<dcomplex, 2> evec_sl = evec(range(), range(), grid.index());
std::tie (eval_sl,evec_sl) = linalg::eigenelements( TK( (*grid) (range(0,ndim)))); //, true); std::tie(eval_sl, evec_sl) = linalg::eigenelements(TK((*grid)(range(0, ndim)))); //, true);
//cerr<< " point "<< *grid << " value "<< eval_sl<< endl; //" "<< (*grid) (range(0,ndim)) << endl; // cerr<< " point "<< *grid << " value "<< eval_sl<< endl; //" "<< (*grid) (range(0,ndim)) << endl;
} }
// define the epsilon mesh, etc. // define the epsilon mesh, etc.
array<double,1> epsilon(neps); array<double, 1> epsilon(neps);
double epsmax = tqa::max_element(eval); double epsmax = max_element(eval);
double epsmin = tqa::min_element(eval); double epsmin = min_element(eval);
double deps=(epsmax-epsmin)/neps; double deps = (epsmax - epsmin) / neps;
//for (size_t i =0; i< neps; ++i) epsilon(i)= epsmin+i/(neps-1.0)*(epsmax-epsmin); // for (int i =0; i< neps; ++i) epsilon(i)= epsmin+i/(neps-1.0)*(epsmax-epsmin);
for (size_t i =0; i< neps; ++i) epsilon(i)=epsmin+(i+0.5)*deps; for (int i = 0; i < neps; ++i) epsilon(i) = epsmin + (i + 0.5) * deps;
// bin the eigenvalues according to their energy // bin the eigenvalues according to their energy
// NOTE: a is defined as an integer. it is the index for the DOS. // NOTE: a is defined as an integer. it is the index for the DOS.
//REPORT <<"Starting Binning ...."<<endl; // REPORT <<"Starting Binning ...."<<endl;
array<double,2> rho (neps,norb);rho()=0; array<double, 2> rho(neps, norb);
for(size_t l=0;l<norb;l++){ rho() = 0;
for (size_t j=0;j<grid.size();j++){ for (int l = 0; l < norb; l++) {
for (size_t k=0;k<norb;k++){ for (int j = 0; j < grid.size(); j++) {
int a=int((eval(k,j)-epsmin)/deps); for (int k = 0; k < norb; k++) {
if(a==int(neps)) a=a-1; int a = int((eval(k, j) - epsmin) / deps);
rho(a,l) += real(conj(evec(l,k,j))*evec(l,k,j)); if (a == int(neps)) a = a - 1;
//dos(a) += real(conj(evec(l,k,j))*evec(l,k,j)); rho(a, l) += real(conj(evec(l, k, j)) * evec(l, k, j));
// dos(a) += real(conj(evec(l,k,j))*evec(l,k,j));
} }
} }
} }
//rho = rho / double(grid.size()*deps); // rho = rho / double(grid.size()*deps);
rho /= grid.size()*deps; rho /= grid.size() * deps;
return std::make_pair( epsilon, rho); return std::make_pair(epsilon, rho);
} }
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
std::pair<array<double,1>, array<double,1> > dos_patch(tight_binding const & TB, const array<double,2> & triangles, size_t neps, size_t ndiv) { std::pair<array<double, 1>, array<double, 1>> dos_patch(tight_binding const& TB, const array<double, 2>& triangles, int neps,
int ndiv) {
// WARNING: This version only works for a single band Hamiltonian in 2 dimensions!!!! // WARNING: This version only works for a single band Hamiltonian in 2 dimensions!!!!
// triangles is an array of points defining the triangles of the patch // triangles is an array of points defining the triangles of the patch
// neps in the number of bins in energy // neps in the number of bins in energy
// ndiv in the number of divisions used to divide the triangles // ndiv in the number of divisions used to divide the triangles
//const size_t ndim=TB.lattice().dim(); // int ndim=TB.lattice().dim();
//const size_t norb=TB.lattice().n_orbitals(); // int norb=TB.lattice().n_orbitals();
int ntri = triangles.shape(0)/3; int ntri = triangles.shape(0) / 3;
array<double,1> dos(neps); array<double, 1> dos(neps);
// Check consistency // Check consistency
const size_t ndim=TB.lattice().dim(); int ndim = TB.lattice().dim();
//const size_t norb=TB.lattice().n_orbitals(); // int norb=TB.lattice().n_orbitals();
if (ndim !=2) TRIQS_RUNTIME_ERROR<<"dos_patch : dimension 2 only !"; if (ndim != 2) TRIQS_RUNTIME_ERROR << "dos_patch : dimension 2 only !";
if (triangles.shape(1) != ndim) TRIQS_RUNTIME_ERROR<<"dos_patch : the second dimension of the 'triangle' array in not "<<ndim; if (triangles.shape(1) != ndim)
TRIQS_RUNTIME_ERROR << "dos_patch : the second dimension of the 'triangle' array in not " << ndim;
// Every triangle has ndiv*ndiv k points // Every triangle has ndiv*ndiv k points
size_t nk = ntri*ndiv*ndiv; int nk = ntri * ndiv * ndiv;
size_t k_index = 0; int k_index = 0;
double epsmax=-100000,epsmin=100000; double epsmax = -100000, epsmin = 100000;
array<dcomplex,2> thop(1,1); array<dcomplex, 2> thop(1, 1);
array<double,1> energ(nk), weight(nk); array<double, 1> energ(nk), weight(nk);
// a, b, c are the corners of the triangle // a, b, c are the corners of the triangle
// g the center of gravity taken from a // g the center of gravity taken from a
array<double,1> a(ndim), b(ndim), c(ndim), g(ndim), rv(ndim); array<double, 1> a(ndim), b(ndim), c(ndim), g(ndim), rv(ndim);
int pt = 0; int pt = 0;
double s, t; double s, t;
// The Fourier transform of TK // The fourier transform of TK
auto TK = Fourier(TB); auto TK = fourier(TB);
// loop over the triangles // loop over the triangles
for (int tri = 0; tri < ntri; tri++) { for (int tri = 0; tri < ntri; tri++) {
a = triangles(pt,range()); a = triangles(pt, range());
pt++; pt++;
b = triangles(pt,range()); b = triangles(pt, range());
pt++; pt++;
c = triangles(pt,range()); c = triangles(pt, range());
pt++; pt++;
g = ((a+b+c)/3.0-a)/double(ndiv); g = ((a + b + c) / 3.0 - a) / double(ndiv);
// the area around a k point might be different from one triangle to the other // the area around a k point might be different from one triangle to the other
// so I use it to weight the sum in the dos // so I use it to weight the sum in the dos
double area = abs(0.5*((b(0)-a(0))*(c(1)-a(1))-(b(1)-a(1))*(c(0)-a(0)))/(ndiv*ndiv)); double area = abs(0.5 * ((b(0) - a(0)) * (c(1) - a(1)) - (b(1) - a(1)) * (c(0) - a(0))) / (ndiv * ndiv));
for (size_t i = 0; i<ndiv; i++) { for (int i = 0; i < ndiv; i++) {
s = i/double(ndiv); s = i / double(ndiv);
for (size_t j = 0; j<ndiv-i; j++) { for (int j = 0; j < ndiv - i; j++) {
t = j/double(ndiv); t = j / double(ndiv);
for (size_t k = 0; k<2; k++) { for (int k = 0; k < 2; k++) {
rv = a+s*(b-a)+t*(c-a)+(k+1.0)*g; rv = a + s * (b - a) + t * (c - a) + (k + 1.0) * g;
if(k==0 || j < ndiv-i-1) { if (k == 0 || j < ndiv - i - 1) {
energ(k_index) = real(TK(rv)(0,0)); energ(k_index) = real(TK(rv)(0, 0));
//compute(rv); // compute(rv);
//energ(k_index) = real(tk_for_eval(1,1)); //tk_for_eval is Fortran array // energ(k_index) = real(tk_for_eval(1,1)); //tk_for_eval is Fortran array
weight(k_index) = area; weight(k_index) = area;
if (energ(k_index)>epsmax) epsmax=energ(k_index); if (energ(k_index) > epsmax) epsmax = energ(k_index);
if (energ(k_index)<epsmin) epsmin=energ(k_index); if (energ(k_index) < epsmin) epsmin = energ(k_index);
k_index++; k_index++;
} }
} }
@ -196,27 +212,23 @@ using namespace std;
assert(k_index == nk); assert(k_index == nk);
// define the epsilon mesh, etc. // define the epsilon mesh, etc.
array<double,1> epsilon(neps); array<double, 1> epsilon(neps);
double deps=(epsmax-epsmin)/neps; double deps = (epsmax - epsmin) / neps;
for (size_t i =0; i< neps; ++i) epsilon(i)= epsmin+i/(neps-1.0)*(epsmax-epsmin); for (int i = 0; i < neps; ++i) epsilon(i) = epsmin + i / (neps - 1.0) * (epsmax - epsmin);
// bin the eigenvalues according to their energy // bin the eigenvalues according to their energy
int ind; int ind;
double totalweight(0.0); double totalweight(0.0);
dos() = 0.0; dos() = 0.0;
for (size_t j = 0; j < nk; j++) { for (int j = 0; j < nk; j++) {
ind=int((energ(j)-epsmin)/deps); ind = int((energ(j) - epsmin) / deps);
if (ind == int(neps)) ind--; if (ind == int(neps)) ind--;
dos(ind) += weight(j); dos(ind) += weight(j);
totalweight += weight(j); totalweight += weight(j);
} }
dos /= deps;// Normalize the DOS dos /= deps; // Normalize the DOS
return std::make_pair(epsilon, dos); return {std::move(epsilon), std::move(dos)};
} }
}
}
}}

View File

@ -18,74 +18,82 @@
* TRIQS. If not, see <http://www.gnu.org/licenses/>. * TRIQS. If not, see <http://www.gnu.org/licenses/>.
* *
******************************************************************************/ ******************************************************************************/
#ifndef TRIQS_LATTICE_TIGHTBINDINGS_H #pragma once
#define TRIQS_LATTICE_TIGHTBINDINGS_H #include "brillouin_zone.hpp"
#include "bravais_lattice_and_brillouin_zone.hpp" #include <triqs/utility/complex_ops.hpp>
namespace triqs { namespace lattice_tools { namespace triqs {
namespace lattice {
/** /**
For tightbinding Hamiltonian with fully localised orbitals For tightbinding Hamiltonian with fully localised orbitals
Model the ShortRangeFunctionOnBravaisLattice concept.
Overlap between orbital is taken as unit matrix. Overlap between orbital is taken as unit matrix.
*/ */
class tight_binding { class tight_binding {
typedef std::vector<std::pair<std::vector<long>, matrix<dcomplex>>> displ_value_stack_t;
displ_value_stack_t displ_value_stack;
bravais_lattice bl_;
public :
typedef std::vector<long> arg_type;
/// bravais_lattice bl_;
tight_binding (bravais_lattice const & bl) : bl_(bl) {}; std::vector<std::vector<long>> all_disp;
std::vector<matrix<dcomplex>> all_matrices;
/// Underlying lattice public:
bravais_lattice const & lattice() const { return bl_;} ///
tight_binding(bravais_lattice const& bl, std::vector<std::vector<long>> all_disp, std::vector<matrix<dcomplex>> all_matrices);
/// Number of bands, i.e. size of the matrix t(k) /// Underlying lattice
size_t n_bands() const { return bl_.n_orbitals();} bravais_lattice const& lattice() const { return bl_; }
/** /// Number of bands, i.e. size of the matrix t(k)
* Push_back mechanism of a pair displacement -> matrix int n_bands() const { return bl_.n_orbitals(); }
* VectorIntType is anything from which a std::vector<long> can be constructed
* MatrixDComplexType is anything from which a matrix<dcomplex> can be constructed
*/
template<typename VectorIntType, typename MatrixDComplexType>
void push_back(VectorIntType && v, MatrixDComplexType && m) {
std::vector<long> V(std::forward<VectorIntType>(v));
if (v.size() != bl_.dim()) TRIQS_RUNTIME_ERROR<<"tight_binding : displacement of incorrect size : got "<< v.size() << "instead of "<< bl_.dim();
matrix<dcomplex> M(std::forward<MatrixDComplexType>(m));
if (first_dim(M) != n_bands()) TRIQS_RUNTIME_ERROR<<"tight_binding : the first dim matrix is of size "<< first_dim(M) <<" instead of "<< n_bands();
if (second_dim(M) != n_bands()) TRIQS_RUNTIME_ERROR<<"tight_binding : the first dim matrix is of size "<< second_dim(M) <<" instead of "<< n_bands();
displ_value_stack.push_back(std::make_pair(std::move(V), std::move(M)));
}
void reserve(size_t n) { displ_value_stack.reserve(n);} // calls F(R, t(R)) for all R
template <typename F> friend void foreach(tight_binding const& tb, F f) {
int n = tb.all_disp.size();
for (int i = 0; i < n; ++i) f(tb.all_disp[i], tb.all_matrices[i]);
}
// iterators // a simple function on the domain brillouin_zone
typedef displ_value_stack_t::const_iterator const_iterator; struct fourier_impl {
typedef displ_value_stack_t::iterator iterator; tight_binding const& tb;
const_iterator begin() const { return displ_value_stack.begin();} const int nb;
const_iterator end() const { return displ_value_stack.end();}
iterator begin() { return displ_value_stack.begin();} using domain_t = brillouin_zone;
iterator end() { return displ_value_stack.end();} brillouin_zone domain() const {
}; return {tb.lattice()};
}
template <typename K> matrix<dcomplex> operator()(K const& k) {
matrix<dcomplex> res(nb, nb);
res() = 0;
foreach(tb, [&](std::vector<long> const& displ, matrix<dcomplex> const& m) {
double dot_prod = 0;
int imax = displ.size();
for (int i = 0; i < imax; ++i) dot_prod += k(i) * displ[i];
//double dot_prod = k(0) * displ[0] + k(1) * displ[1];
res += m * exp(2_j * M_PI * dot_prod);
});
return res;
}
};
fourier_impl friend fourier(tight_binding const& tb) {
return {tb, tb.n_bands()};
}
}; // tight_binding
/** /**
Factorized version of hopping (for speed) Factorized version of hopping (for speed)
k_in[:,n] is the nth vector k_in[:,n] is the nth vector
In the result, R[:,:,n] is the corresponding hopping t(k) In the result, R[:,:,n] is the corresponding hopping t(k)
*/ */
array_view <dcomplex,3> hopping_stack (tight_binding const & TB, array_view<double,2> const & k_stack); array<dcomplex, 3> hopping_stack(tight_binding const& TB, arrays::array_const_view<double, 2> k_stack);
// not optimal ordering here // not optimal ordering here
std::pair<array<double,1>, array<double,2> > dos(tight_binding const & TB, size_t nkpts, size_t neps); std::pair<array<double, 1>, array<double, 2>> dos(tight_binding const& TB, int nkpts, int neps);
std::pair<array<double,1>, array<double,1> > dos_patch(tight_binding const & TB, const array<double,2> & triangles, size_t neps, size_t ndiv); std::pair<array<double, 1>, array<double, 1>> dos_patch(tight_binding const& TB, const array<double, 2>& triangles, int neps,
array_view<double,2> energies_on_bz_path(tight_binding const & TB, K_view_type K1, K_view_type K2, size_t n_pts); int ndiv);
array_view<double,2> energies_on_bz_grid(tight_binding const & TB, size_t n_pts); array<double, 2> energies_on_bz_path(tight_binding const& TB, k_t const& K1, k_t const& K2, int n_pts);
array<double, 2> energies_on_bz_grid(tight_binding const& TB, int n_pts);
}} }
}
#endif