/*******************************************************************************
*
* TRIQS: a Toolbox for Research in Interacting Quantum Systems
*
* Copyright (C) 2014 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 .
*
******************************************************************************/
#pragma once
#include
#include
#include "./brillouin_zone.hpp"
#include "../gfs/tools.hpp"
#include "../gfs/meshes/mesh_tools.hpp"
namespace triqs {
namespace lattice {
class regular_bz_mesh {
brillouin_zone bz; //
utility::mini_vector dims = {1, 1, 1}; // the size in each dimension
size_t _size = dims[0] * dims[1] * dims[2]; // total size
long s1 = dims[0]; // stride
long s2 = dims[0] * dims[1]; // stride
utility::mini_vector step = {2 * M_PI / dims[0], 2 * M_PI / dims[1], 2 * M_PI / dims[2]};
public:
regular_bz_mesh() = default;
regular_bz_mesh(brillouin_zone const& bz, int n_l)
: bz(bz), dims{n_l, (bz.lattice().dim() >= 2 ? n_l : 1), (bz.lattice().dim() >= 3 ? n_l : 1)} {}
int rank() const { return (dims[2] > 1 ? 3 : (dims[1] > 1 ? 2 : 1)); }
utility::mini_vector get_dimensions() const { return dims; }
/// ----------- Model the mesh concept ----------------------
using domain_t = brillouin_zone;
using domain_pt_t = typename domain_t::point_t;
domain_t const& domain() const { return bz; }
using index_t = utility::mini_vector;
using linear_index_t = long;
size_t size() const { return _size; }
utility::mini_vector size_of_components() const {
return {size()};
}
k_t index_to_point(index_t const& i) const {
return {i[0] * step[0], i[1] * step[1], i[2] * step[2]};
//return {(i[0] + 0.5) * step[0], (i[1] + 0.5) * step[1], (i[2] + 0.5) * step[2]};
}
// flatten the index
linear_index_t index_to_linear(index_t const& i) const { return i[0] + i[1] * s1 + i[2] * s2; }
// f (k) -> void where k is a k_t, a point in the BZ
template friend void foreach(regular_bz_mesh const& m, F f) {
k_t k = {0,0,0}; //{0.5 * m.step[0], 0.5 * m.step[1], 0.5 * m.step[2]};
for (long i2 = 0; i2 < m.dims[2]; ++i2, k(2) += m.step[2])
for (long i1 = 0; i1 < m.dims[1]; ++i1, k(1) += m.step[1])
for (long i0 = 0; i0 < m.dims[0]; ++i0, k(0) += m.step[0]) f(k);
}
/// The wrapper for the mesh point
class mesh_point_t : public utility::index3_generator, public utility::arithmetic_ops_by_cast {
regular_bz_mesh const* m = nullptr;
public:
mesh_point_t() = default;
mesh_point_t(regular_bz_mesh const& mesh, index_t const& index) : index3_generator(mesh.get_dimensions(), index), m(&mesh) {}
mesh_point_t(regular_bz_mesh const& mesh) : mesh_point_t(mesh, {0,0,0}) {}
operator domain_pt_t() const { return m->index_to_point(index()); }
linear_index_t linear_index() const { return m->index_to_linear(index()); }
// The mesh point behaves like a vector // NOT GOOD : take the ith componenet, this is SLOW
double operator()(int i) const { return index()[i] * m->step[i]; }
//double operator()(int i) const { return (index()[i] + 0.5) * m->step[i]; }
double operator[](int i) const { return operator()(i);}
friend std::ostream& operator<<(std::ostream& out, mesh_point_t const& x) { return out << (domain_pt_t)x; }
};
/// Accessing a point of the mesh
mesh_point_t operator[](index_t i) const {
return {*this, i};
}
/// Iterating on all the points...
using const_iterator = gfs::mesh_pt_generator;
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); }
/// ----------- End mesh concept ----------------------
/// locate the closest point
mesh_point_t locate_neighbours(k_t const& k) const {
auto l = [&](int i) {
long r = std::lround(k(i) / step[i]) % dims[i];
return (r >= 0 ? r : r + dims[i]);
};
return {*this, {l(0), l(1), l(2)}};
}
/// Write into HDF5
friend void h5_write(h5::group fg, std::string subgroup_name, regular_bz_mesh const& m) {
h5::group gr = fg.create_group(subgroup_name);
h5_write(gr, "domain", m.domain());
h5_write(gr, "n_pts", m.dims[2]);
//h5_write(gr, "dims", m.dims.to_vector());
}
/// Read from HDF5
friend void h5_read(h5::group fg, std::string subgroup_name, regular_bz_mesh& m) {
h5::group gr = fg.open_group(subgroup_name);
auto bz = h5::h5_read(gr, "domain");
auto dims = h5::h5_read(gr, "n_pts");
m = regular_bz_mesh(bz, dims);
//auto dims = h5::h5_read>(gr, "dims");
//m = regular_bz_mesh(bz, {dims[0], dims[1], dims[2]}); // NOT CORRECT IN GENERAL
}
// BOOST Serialization
friend class boost::serialization::access;
template void serialize(Archive& ar, const unsigned int version) {
ar& TRIQS_MAKE_NVP("dims", dims);
ar& TRIQS_MAKE_NVP("_size", _size);
ar& TRIQS_MAKE_NVP("s2", s2);
ar& TRIQS_MAKE_NVP("s1", s1);
ar& TRIQS_MAKE_NVP("step", step);
}
};
}
}