.. _program_listing_file_src_phonon.hpp: Program Listing for File phonon.hpp =================================== |exhale_lsh| :ref:`Return to documentation for file ` (``src/phonon.hpp``) .. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS .. code-block:: cpp /* This file is part of brille. Copyright © 2020 Greg Tucker brille is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. brille 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 Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with brille. If not, see . */ #ifndef BRILLE_PHONON_HPP_ #define BRILLE_PHONON_HPP_ #include #include #include "array_latvec.hpp" // defines bArray namespace brille { class RotateTable{}; class GammaTable: public RotateTable { public: using ind_t = unsigned; private: std::vector point2space_; // use std::vectors instead of std::map for the mapping since we know the // total number of keys and how to calculate their positions in the vector ind_t n_atoms; ind_t n_sym_ops; std::vector l_mapping; std::vector v_mapping; Direct lattice_; bArray vectors_; public: explicit GammaTable(): n_atoms(0), n_sym_ops(0) { l_mapping.resize(0); v_mapping.resize(0); } GammaTable(const Direct& dlat, const int time_reversal=0){ this->construct(dlat, time_reversal); } bool construct(const Direct& dlat, const int time_reversal=0){ lattice_ = dlat; PointSymmetry ps = dlat.get_pointgroup_symmetry(time_reversal); Symmetry spgsym = dlat.get_spacegroup_symmetry(time_reversal); Basis bs = dlat.get_basis(); // resize all vectors/arrays n_atoms = bs.size(); n_sym_ops = ps.size(); point2space_.resize(n_sym_ops); l_mapping.resize(n_atoms*n_sym_ops); v_mapping.resize(n_atoms*n_sym_ops); vectors_ = bArray({n_atoms*n_sym_ops+1u, 3u}, 0.); // always put (0,0,0) first // construct a mapping of pointgroup indices to spacegroup indices // -- this mapping is likely not invertable, but it shouldn't (doesn't?) // matter. I think. for (ind_t i=0; i=spgsym.size()){ info_update("The point group operation\n",ps.get(i),"was not found in the spacegroup!"); throw std::runtime_error("Something has gone wrong with the correspondence of spacegroup to pointgroup"); } } ind_t count{1u}; // for (0,0,0) // fill in the mappings for (ind_t k=0; k vec = motion.inverse().move_point(bs.position(l)); auto rk = bs.position(k); for (int i=0; i<3; ++i) vec[i] -= rk[i]; // check if this vector is in vectors_ // look for an equal vector within the first count vectors_ -- return its index, or count if none match // count >= 1, so view is fine: ind_t v = norm(vectors_.view(0,count) - vec).is(brille::cmp::eq, 0.).first(); // store the vector if its not already present if (count == v) vectors_.set(count++, vec); ind_t key = this->calc_key(k, r); l_mapping[key] = l; v_mapping[key] = v; } vectors_.resize(count); // not really necessary memory copy? return true; } template ind_t F0(Ik k, Ir r) const { return l_mapping[this->calc_key(k,r)]; } const bArray& vectors() const {return vectors_;} template ind_t vector_index(Ik k, Ir r) const { return v_mapping[this->calc_key(k,r)]; } template bArray vector(Ik k, Ir r) const { return vectors_.extract(this->vector_index(k,r)); // aternatively // return vectors_.view(this->vector_index(k,r)); } template LDVec ldvector(Ik k, Ir r) const { return LDVec(lattice_, this->vector(k,r)); } const Direct& lattice() const {return lattice_;} private: template ind_t calc_key(Ik k, Ir r) const { if (k(k)*n_sym_ops + static_cast(r); throw std::runtime_error("Attempting to access out of bounds mapping!"); } }; } // namespace brille #endif