Newer
Older
#include "MantidGeometry/Crystal/PointGroup.h"
#include "MantidKernel/System.h"
#include <set>
#include <boost/make_shared.hpp>
#include <boost/algorithm/string.hpp>
#include "MantidGeometry/Crystal/PointGroupFactory.h"
#include "MantidGeometry/Crystal/SymmetryOperationFactory.h"
#include "MantidGeometry/Crystal/SymmetryElementFactory.h"
namespace Mantid {
namespace Geometry {
using Kernel::V3D;
using Kernel::IntMatrix;
/**
* Returns all equivalent reflections for the supplied hkl.
*
* This method returns a vector containing all equivalent hkls for the supplied
* one. It depends on the internal state of the pointgroup object (e.g. which
* symmetry operations and therefore, which transformation matrices are
* present). This internal state is unique for each concrete point group and
* is set in the constructor.
*
* The returned vector always contains a set of unique hkls, so for special hkls
* like (100), it has fewer entries than for a general hkl. See also
* PointGroup::getEquivalentSet.
*
* @param hkl :: Arbitrary hkl
* @return :: std::vector containing all equivalent hkls.
*/
std::vector<V3D> PointGroup::getEquivalents(const V3D &hkl) const {
return getEquivalentSet(hkl);
}
/**
* Returns the same V3D for all equivalent hkls.
*
* This method is closely related to PointGroup::getEquivalents. It returns the
* same V3D for all hkls of one "family". For example in a cubic point group
* it will return (100) for (001), (010), (0-10), etc.
*
* It can be used to generate a set of symmetry independent hkls, useful for
*
* @param hkl :: Arbitrary hkl
* @return :: hkl specific to a family of index-triplets
*/
V3D PointGroup::getReflectionFamily(const Kernel::V3D &hkl) const {
return *getEquivalentSet(hkl).begin();
}
/// Protected constructor - can not be used directly.
PointGroup::PointGroup(const std::string &symbolHM, const Group &group,
const std::string &description)
: Group(group), m_symbolHM(symbolHM),
m_name(symbolHM + " (" + description + ")") {
m_crystalSystem = getCrystalSystemFromGroup();
m_latticeSystem = getLatticeSystemFromCrystalSystemAndGroup(m_crystalSystem);
PointGroup::PointGroup(const PointGroup &other)
: Group(other), m_symbolHM(other.m_symbolHM), m_name(other.m_name),
m_crystalSystem(other.m_crystalSystem),
m_latticeSystem(other.m_latticeSystem) {}
PointGroup &PointGroup::operator=(const PointGroup &other) {
Group::operator=(other);
m_symbolHM = other.m_symbolHM;
m_name = other.m_name;
m_crystalSystem = other.m_crystalSystem;
m_latticeSystem = other.m_latticeSystem;
return *this;
}
/// Hermann-Mauguin symbol
std::string PointGroup::getSymbol() const { return m_symbolHM; }
bool PointGroup::isEquivalent(const Kernel::V3D &hkl,
const Kernel::V3D &hkl2) const {
std::vector<V3D> hklEquivalents = getEquivalentSet(hkl);
return (std::find(hklEquivalents.begin(), hklEquivalents.end(), hkl2) !=
hklEquivalents.end());
/**
* Generates a set of hkls
*
* This method applies all transformation matrices to the supplied hkl and puts
* it into a set, which is returned in the end. Using a set ensures that each
* hkl occurs once and only once. This set is the set of equivalent hkls,
* specific to a concrete point group.
*
* The symmetry operations need to be set prior to calling this method by a call
* to PointGroup::setTransformationMatrices.
*
* @param hkl :: Arbitrary hkl
* @return :: set of hkls.
*/
std::vector<V3D> PointGroup::getEquivalentSet(const Kernel::V3D &hkl) const {
std::vector<V3D> equivalents;
equivalents.reserve(m_allOperations.size());
for (auto op = m_allOperations.begin(); op != m_allOperations.end(); ++op) {
equivalents.push_back((*op).transformHKL(hkl));
std::sort(equivalents.begin(), equivalents.end(), std::greater<V3D>());
equivalents.erase(std::unique(equivalents.begin(), equivalents.end()),
equivalents.end());
return equivalents;
PointGroup::CrystalSystem PointGroup::getCrystalSystemFromGroup() const {
std::map<std::string, std::set<V3D>> symbolMap;
for (auto op = m_allOperations.begin(); op != m_allOperations.end(); ++op) {
SymmetryElementWithAxis_sptr element =
boost::dynamic_pointer_cast<SymmetryElementWithAxis>(
SymmetryElementFactory::Instance().createSymElement(*op));
if (element) {
std::string symbol = element->hmSymbol();
V3D axis = element->getAxis();
symbolMap[symbol].insert(axis);
}
}
if (symbolMap["3"].size() == 4) {
return CrystalSystem::Cubic;
}
if (symbolMap["6"].size() == 1 || symbolMap["-6"].size() == 1) {
return CrystalSystem::Hexagonal;
}
if (symbolMap["3"].size() == 1) {
return CrystalSystem::Trigonal;
}
if (symbolMap["4"].size() == 1 || symbolMap["-4"].size() == 1) {
return CrystalSystem::Tetragonal;
}
if (symbolMap["2"].size() == 3 ||
(symbolMap["2"].size() == 1 && symbolMap["m"].size() == 2)) {
return CrystalSystem::Orthorhombic;
}
if (symbolMap["2"].size() == 1 || symbolMap["m"].size() == 1) {
return CrystalSystem::Monoclinic;
}
return CrystalSystem::Triclinic;
}
PointGroup::LatticeSystem PointGroup::getLatticeSystemFromCrystalSystemAndGroup(
const CrystalSystem &crystalSystem) const {
switch (crystalSystem) {
case CrystalSystem::Cubic:
return LatticeSystem::Cubic;
case CrystalSystem::Hexagonal:
return LatticeSystem::Hexagonal;
case CrystalSystem::Tetragonal:
return LatticeSystem::Tetragonal;
case CrystalSystem::Orthorhombic:
return LatticeSystem::Orthorhombic;
case CrystalSystem::Monoclinic:
return LatticeSystem::Monoclinic;
case CrystalSystem::Triclinic:
return LatticeSystem::Triclinic;
default: {
if (getCoordinateSystem() == Group::Hexagonal) {
return LatticeSystem::Hexagonal;
}
return LatticeSystem::Rhombohedral;
}
}
}
/** @return a vector with all possible PointGroup objects */
std::vector<PointGroup_sptr> getAllPointGroups() {
std::vector<std::string> allSymbols =
PointGroupFactory::Instance().getAllPointGroupSymbols();
std::vector<PointGroup_sptr> out;
for (auto it = allSymbols.begin(); it != allSymbols.end(); ++it) {
out.push_back(PointGroupFactory::Instance().createPointGroup(*it));
}
return out;
}
PointGroupCrystalSystemMap getPointGroupsByCrystalSystem() {
PointGroupCrystalSystemMap map;
std::vector<PointGroup_sptr> pointGroups = getAllPointGroups();
for (size_t i = 0; i < pointGroups.size(); ++i) {
map.insert(std::make_pair(pointGroups[i]->crystalSystem(), pointGroups[i]));
}
return map;
}
/// Return a human-readable string for the given crystal system
std::string
getCrystalSystemAsString(const PointGroup::CrystalSystem &crystalSystem) {
switch (crystalSystem) {
case PointGroup::CrystalSystem::Cubic:
return "Cubic";
case PointGroup::CrystalSystem::Tetragonal:
return "Tetragonal";
case PointGroup::CrystalSystem::Hexagonal:
return "Hexagonal";
case PointGroup::CrystalSystem::Trigonal:
return "Trigonal";
case PointGroup::CrystalSystem::Orthorhombic:
return "Orthorhombic";
case PointGroup::CrystalSystem::Monoclinic:
return "Monoclinic";
default:
return "Triclinic";
}
}
PointGroup::CrystalSystem
getCrystalSystemFromString(const std::string &crystalSystem) {
std::string crystalSystemLC = boost::algorithm::to_lower_copy(crystalSystem);
if (crystalSystemLC == "cubic") {
return PointGroup::CrystalSystem::Cubic;
} else if (crystalSystemLC == "tetragonal") {
return PointGroup::CrystalSystem::Tetragonal;
} else if (crystalSystemLC == "hexagonal") {
return PointGroup::CrystalSystem::Hexagonal;
} else if (crystalSystemLC == "trigonal") {
return PointGroup::CrystalSystem::Trigonal;
} else if (crystalSystemLC == "orthorhombic") {
return PointGroup::CrystalSystem::Orthorhombic;
} else if (crystalSystemLC == "monoclinic") {
return PointGroup::CrystalSystem::Monoclinic;
} else if (crystalSystemLC == "triclinic") {
return PointGroup::CrystalSystem::Triclinic;
} else {
throw std::invalid_argument("Not a valid crystal system: '" +
crystalSystem + "'.");
}
}
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
std::string
getLatticeSystemAsString(const PointGroup::LatticeSystem &latticeSystem) {
switch (latticeSystem) {
case PointGroup::LatticeSystem::Cubic:
return "Cubic";
case PointGroup::LatticeSystem::Tetragonal:
return "Tetragonal";
case PointGroup::LatticeSystem::Hexagonal:
return "Hexagonal";
case PointGroup::LatticeSystem::Rhombohedral:
return "Rhombohedral";
case PointGroup::LatticeSystem::Orthorhombic:
return "Orthorhombic";
case PointGroup::LatticeSystem::Monoclinic:
return "Monoclinic";
default:
return "Triclinic";
}
}
PointGroup::LatticeSystem
getLatticeSystemFromString(const std::string &latticeSystem) {
std::string latticeSystemLC = boost::algorithm::to_lower_copy(latticeSystem);
if (latticeSystemLC == "cubic") {
return PointGroup::LatticeSystem::Cubic;
} else if (latticeSystemLC == "tetragonal") {
return PointGroup::LatticeSystem::Tetragonal;
} else if (latticeSystemLC == "hexagonal") {
return PointGroup::LatticeSystem::Hexagonal;
} else if (latticeSystemLC == "rhombohedral") {
return PointGroup::LatticeSystem::Rhombohedral;
} else if (latticeSystemLC == "orthorhombic") {
return PointGroup::LatticeSystem::Orthorhombic;
} else if (latticeSystemLC == "monoclinic") {
return PointGroup::LatticeSystem::Monoclinic;
} else if (latticeSystemLC == "triclinic") {
return PointGroup::LatticeSystem::Triclinic;
} else {
throw std::invalid_argument("Not a valid lattice system: '" +
latticeSystem + "'.");
}
}
} // namespace Mantid
} // namespace Geometry