#include "MantidGeometry/Crystal/SpaceGroup.h" #include "MantidGeometry/Crystal/PointGroupFactory.h" #include <algorithm> namespace Mantid { namespace Geometry { using namespace Kernel; /** * Constructor * * This constructor creates a space group with the symmetry operations contained * in the Group-parameter and assigns the given number and symbol. * * @param itNumber :: Space group number (ITA) * @param hmSymbol :: Herman-Mauguin symbol for the space group * @param group :: Group that contains all symmetry operations (including *centering). */ SpaceGroup::SpaceGroup(size_t itNumber, const std::string &hmSymbol, const Group &group) : Group(group), m_number(itNumber), m_hmSymbol(hmSymbol) {} /// Copy constructor SpaceGroup::SpaceGroup(const SpaceGroup &other) : Group(other), m_number(other.m_number), m_hmSymbol(other.m_hmSymbol) {} /// Assignment operator, utilizes Group's assignment operator SpaceGroup &SpaceGroup::operator=(const SpaceGroup &other) { Group::operator=(other); m_number = other.m_number; m_hmSymbol = other.m_hmSymbol; return *this; } /// Returns the stored space group number size_t SpaceGroup::number() const { return m_number; } /// Returns the stored Hermann-Mauguin symbol std::string SpaceGroup::hmSymbol() const { return m_hmSymbol; } /** * Returns whether the given reflection is allowed or not in this space group * * Space groups that contain translational symmetry cause certain reflections * to be absent due to the contributions of symmetry equivalent atoms to the * structure factor cancelling out. This method implements the procedure * described in ITA [1] to check whether a reflection is allowed or not * according to the symmetry operations in the space group. Please note that * certain arrangements of atoms can lead to additional conditions that can not * be determined using a space group's symmetry operations alone. For these * situations, Geometry::CrystalStructure can help. * * [1] International Tables for Crystallography (2006). Vol. A, ch. 12.3, p. 832 * * @param hkl :: HKL to be checked. * @return :: true if the reflection is allowed, false otherwise. */ bool SpaceGroup::isAllowedReflection(const Kernel::V3D &hkl) const { for (const auto &m_allOperation : m_allOperations) { if (m_allOperation.hasTranslation()) { /* Floating point precision problem: * (H . v) % 1.0 is not always exactly 0, so instead: * | [(H . v) + delta] % 1.0 | > 1e-14 is checked * The transformation is only performed if necessary. */ if ((fabs(fmod(fabs(hkl.scalar_prod(m_allOperation.reducedVector())) + 1e-15, 1.0)) > 1e-14) && (m_allOperation.transformHKL(hkl) == hkl)) { return false; } } } return true; } /** * Returns the point group of the space group * * This method uses PointGroupFactory to create the point group of the space- * group. Becausethe factory is used for construction, a new object is returned * each time this method is called. * * @return :: PointGroup-object. */ PointGroup_sptr SpaceGroup::getPointGroup() const { return PointGroupFactory::Instance().createPointGroupFromSpaceGroup(*this); } /** * Returns the site symmetry group * * The site symmetry group contains all symmetry operations of a space group * that leave a point unchanged. This method probes the symmetry operations * of the space group and constructs a Group-object using them. * * @param position :: Coordinates of the site. * @return :: Site symmetry group. */ Group_const_sptr SpaceGroup::getSiteSymmetryGroup(const V3D &position) const { V3D wrappedPosition = Geometry::getWrappedVector(position); std::vector<SymmetryOperation> siteSymmetryOps; AtomPositionsEqual comparator; std::copy_if(m_allOperations.begin(),m_allOperations.end(),std::inserter(siteSymmetryOps,siteSymmetryOps.begin()),[&](const SymmetryOperation & op) { return Geometry::getWrappedVector(op * wrappedPosition) == wrappedPosition; }); return GroupFactory::create<Group>(siteSymmetryOps); } } // namespace Geometry } // namespace Mantid