1 #include "atom.h"
2 
3 using namespace Vipster;
4 
atomFmtRelative(AtomFmt f)5 bool Vipster::atomFmtRelative(AtomFmt f)
6 {
7     return f<=AtomFmt::Alat;
8 }
9 
atomFmtAbsolute(AtomFmt f)10 bool Vipster::atomFmtAbsolute(AtomFmt f)
11 {
12     return !atomFmtRelative(f);
13 }
14 
operator ==(const AtomProperties & p1,const AtomProperties & p2)15 bool Vipster::operator==(const AtomProperties &p1, const AtomProperties &p2)
16 {
17     return std::tie(p1.charge, p1.flags, p1.forces)
18            ==
19            std::tie(p2.charge, p2.flags, p2.forces);
20 }
21 
makeConverter(const AtomContext & source,const AtomContext & target)22 detail::CoordConverter Vipster::detail::makeConverter(const AtomContext &source,
23                                                       const AtomContext &target)
24 {
25     switch(source.fmt){
26     case AtomFmt::Crystal:
27         switch(target.fmt){
28         case AtomFmt::Crystal:
29             if(source.cell == target.cell){
30                 return [](const Vec &v){return v;};
31             }else{
32                 return [&](const Vec &v){return v * (source.cell->matrix * source.cell->dimension)
33                                                   * (target.cell->inverse / target.cell->dimension);};
34             }
35         case AtomFmt::Alat:
36             return [&](const Vec &v){return v * (source.cell->matrix * source.cell->dimension)
37                                               / target.cell->dimension;};
38         default:
39             return [&](const Vec &v){return v * (source.cell->matrix * source.cell->dimension)
40                                               * detail::AtomContext::fromAngstrom[target.fmt];};
41         }
42     case AtomFmt::Alat:
43         switch(target.fmt){
44         case AtomFmt::Crystal:
45             if(source.cell->dimension == target.cell->dimension){
46                 return [&](const Vec &v){return v * target.cell->inverse;};
47             }else{
48                 return [&](const Vec &v){return v * source.cell->dimension
49                                                   * (target.cell->inverse / target.cell->dimension);};
50             }
51         case AtomFmt::Alat:
52             if(source.cell->dimension == target.cell->dimension){
53                 return [](const Vec &v){return v;};
54             }else{
55                 return [&](const Vec &v){return v * source.cell->dimension / target.cell->dimension;};
56             }
57         default:
58             return [&](const Vec &v){return v * source.cell->dimension
59                                               * detail::AtomContext::fromAngstrom[target.fmt];};
60         }
61     default: // absolute coordinates
62         switch(target.fmt){
63         case AtomFmt::Crystal:
64             return [&](const Vec &v){return v * detail::AtomContext::toAngstrom[source.fmt]
65                                               * (target.cell->inverse / target.cell->dimension);};
66         case AtomFmt::Alat:
67             return [&](const Vec &v){return v * detail::AtomContext::toAngstrom[source.fmt]
68                                               / target.cell->dimension;};
69         default:
70             if(source.fmt == target.fmt){
71                 return [](const Vec &v){return v;};
72             }else{
73                 return [&](const Vec &v){return v * detail::AtomContext::toAngstrom[source.fmt]
74                                                   * detail::AtomContext::fromAngstrom[target.fmt];};
75             }
76         }
77     }
78 }
79