Program Listing for File primitive.hpp

Return to documentation for file (src/primitive.hpp)

/* This file is part of brille.

Copyright © 2019,2020 Greg Tucker <greg.tucker@stfc.ac.uk>

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 <https://www.gnu.org/licenses/>.            */

#ifndef BRILLE_PRIMITIVE_HPP_
#define BRILLE_PRIMITIVE_HPP_
#include "spg_database.hpp"
namespace brille {

template<class T> std::array<T,9> transpose(const std::array<T,9>& a){
  return std::array<T,9>({a[0],a[3],a[6],a[1],a[4],a[7],a[2],a[5],a[8]});
}

class PrimitiveTransform{
private:
  Bravais bravais;
public:
  PrimitiveTransform(const Bravais c): bravais{c} {}
  [[deprecated("Call with an enum Bravais instead")]] PrimitiveTransform(const Spacegroup& s): bravais{s.bravais} {}
  [[deprecated("Call with an enum Bravais instead")]] PrimitiveTransform(const int hall){
    Spacegroup s(hall);
    this->bravais = s.bravais;
  }
  std::array<double,9> get_P(void) const {
    switch (bravais){
      case Bravais::_: throw std::runtime_error("Invalid Bravais centring");
      case Bravais::I: return {-0.5, 0.5, 0.5,  0.5,-0.5, 0.5,  0.5, 0.5,-0.5};
      case Bravais::F: return {  0 , 0.5, 0.5,  0.5,  0 , 0.5,  0.5, 0.5,  0 };
      case Bravais::A: return {  1 ,  0 ,  0 ,   0 , 0.5,-0.5,   0 , 0.5, 0.5};
      case Bravais::B: return { 0.5,  0 ,-0.5,   0 ,  1 ,  0 ,  0.5,  0 , 0.5};
      case Bravais::C: return { 0.5, 0.5,  0 , -0.5, 0.5,  0 ,   0 ,  0 ,  1 };
      case Bravais::R: return {2./3.,-1./3.,-1./3.,  1./3., 1./3.,-2./3.,  1./3., 1./3., 1./3.};
      default: return {  1 ,  1 ,  1,    1 ,  1 ,  1 ,   1 ,  1 ,  1 };
    }
  }
  std::array<int,9> get_invP(void) const {
    switch (bravais){
      case Bravais::_: throw std::runtime_error("Invalid Bravais centring");
      case Bravais::I: return { 0, 1, 1,  1, 0, 1,  1, 1, 0};
      case Bravais::F: return {-1, 1, 1,  1,-1, 1,  1, 1,-1};
      case Bravais::A: return { 1, 0, 0,  0, 1, 1,  0,-1, 1};
      case Bravais::B: return { 1, 0, 1,  0, 1, 0, -1, 0, 1};
      case Bravais::C: return { 1,-1, 0,  1, 1, 0,  0, 0, 1};
      case Bravais::R: return { 1, 0, 1, -1, 1, 1,  0,-1, 1};
      default: return { 1, 0, 0,  0, 1, 0,  0, 0, 1};
    }
  }
  std::array<double,9> get_Pt(void) const { return transpose(this->get_P()); }
  std::array<int,9> get_invPt(void) const { return transpose(this->get_invP());}
  void print(){
    std::array<double,9> M = this->get_P();
    std::array<int,9> invM = this->get_invP();
    for (int i=0; i<3; ++i){
      printf("%3s", i==1 ? "to" :"");
      for (int j=0; j<3; ++j) printf(" % 4.2f",M[i*3+j]);
      printf("%5s", i==1 ? "from" : "");
      for (int j=0; j<3; ++j) printf(" % 2d",invM[i*3+j]);
      printf("\n");
    }
  }
  bool does_anything() const { return (bravais!=Bravais::P);}
  bool does_nothing() const { return (bravais==Bravais::P);}
  std::string string_repr() const {
    std::string repr = "<" + bravais_string(bravais) + " PrimitiveTransform object>";
    return repr;
  }
};


struct PrimitiveTraits{
  using P = double;
  using invP = int;
};
} // end namespace brille
#endif