Skip to content

Commit

Permalink
Refs #10281. Added ProductGroup class
Browse files Browse the repository at this point in the history
  • Loading branch information
Michael Wedel committed Oct 8, 2014
1 parent 8791052 commit e293a31
Show file tree
Hide file tree
Showing 4 changed files with 220 additions and 0 deletions.
3 changes: 3 additions & 0 deletions Code/Mantid/Framework/Geometry/CMakeLists.txt
Expand Up @@ -10,6 +10,7 @@ set ( SRC_FILES
src/Crystal/OrientedLattice.cpp
src/Crystal/PointGroup.cpp
src/Crystal/PointGroupFactory.cpp
src/Crystal/ProductGroup.cpp
src/Crystal/ReducedCell.cpp
src/Crystal/ReflectionCondition.cpp
src/Crystal/ScalarUtils.cpp
Expand Down Expand Up @@ -118,6 +119,7 @@ set ( INC_FILES
inc/MantidGeometry/Crystal/OrientedLattice.h
inc/MantidGeometry/Crystal/PointGroup.h
inc/MantidGeometry/Crystal/PointGroupFactory.h
inc/MantidGeometry/Crystal/ProductGroup.h
inc/MantidGeometry/Crystal/ReducedCell.h
inc/MantidGeometry/Crystal/ReflectionCondition.h
inc/MantidGeometry/Crystal/ScalarUtils.h
Expand Down Expand Up @@ -269,6 +271,7 @@ set ( TEST_FILES
PointGroupFactoryTest.h
PointGroupTest.h
PolygonEdgeTest.h
ProductGroupTest.h
QuadrilateralTest.h
RectangularDetectorPixelTest.h
RectangularDetectorTest.h
Expand Down
@@ -0,0 +1,70 @@
#ifndef MANTID_GEOMETRY_PRODUCTGROUP_H_
#define MANTID_GEOMETRY_PRODUCTGROUP_H_

#include "MantidGeometry/DllConfig.h"
#include "MantidGeometry/Crystal/Group.h"

namespace Mantid
{
namespace Geometry
{

/** ProductGroup :
ProductGroup objects can be constructed using a string which contains
a series of symmetry operations S_i, separated by semicolons:
x,y,z; -x,-y,-z; x,-y,z
For each symmetry operation, a CyclicGroup G_i object is created. These groups
are then multiplied to form a ProductGroup:
P = G_1 * G_2 * G_3 * ... * G_n
This way, groups with many symmetry operations can be generated from a small
set of generators. This is for example described in [1].
[1] Shmueli, U. Acta Crystallogr. A 40, 559–567 (1984).
http://dx.doi.org/10.1107/S0108767384001161
@author Michael Wedel, Paul Scherrer Institut - SINQ
@date 08/10/2014
Copyright © 2014 PSI-MSS
This file is part of Mantid.
Mantid is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
Mantid 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
File change history is stored at: <https://github.com/mantidproject/mantid>
Code Documentation is available at: <http://doxygen.mantidproject.org>
*/
class MANTID_GEOMETRY_DLL ProductGroup : public Group
{
public:
ProductGroup(const std::string &generators);
ProductGroup(const std::vector<Group_const_sptr> &factorGroups);
virtual ~ProductGroup() { }

protected:
Group_const_sptr getGeneratedGroup(const std::string &generators) const;
std::vector<Group_const_sptr> getFactorGroups(const std::vector<SymmetryOperation> &symmetryOperations) const;
Group_const_sptr getProductGroup(const std::vector<Group_const_sptr> &factorGroups) const;
};


} // namespace Geometry
} // namespace Mantid

#endif /* MANTID_GEOMETRY_PRODUCTGROUP_H_ */
58 changes: 58 additions & 0 deletions Code/Mantid/Framework/Geometry/src/Crystal/ProductGroup.cpp
@@ -0,0 +1,58 @@
#include "MantidGeometry/Crystal/ProductGroup.h"

#include "MantidGeometry/Crystal/SymmetryOperationFactory.h"
#include "MantidGeometry/Crystal/CyclicGroup.h"

namespace Mantid
{
namespace Geometry
{

/// String constructor with semicolon-separated symmetry operations
ProductGroup::ProductGroup(const std::string &generators) :
Group(*(getGeneratedGroup(generators)))
{
}

/// Constructor which directly takes a list of factor groups to form the product
ProductGroup::ProductGroup(const std::vector<Group_const_sptr> &factorGroups) :
Group(*(getProductGroup(factorGroups)))
{
}

/// Generates symmetry operations from the string, creates a CyclicGroup from each operation and multiplies them to form a factor group.
Group_const_sptr ProductGroup::getGeneratedGroup(const std::string &generators) const
{
std::vector<SymmetryOperation> operations = SymmetryOperationFactory::Instance().createSymOps(generators);
std::vector<Group_const_sptr> factorGroups = getFactorGroups(operations);

return getProductGroup(factorGroups);
}

/// Returns a vector of cyclic groups for the given vector of symmetry operations
std::vector<Group_const_sptr> ProductGroup::getFactorGroups(const std::vector<SymmetryOperation> &symmetryOperations) const
{
std::vector<Group_const_sptr> groups;

for(auto it = symmetryOperations.begin(); it != symmetryOperations.end(); ++it) {
groups.push_back(GroupFactory::create<CyclicGroup>((*it).identifier()));
}

return groups;
}

/// Multiplies all supplied groups and returns the result
Group_const_sptr ProductGroup::getProductGroup(const std::vector<Group_const_sptr> &factorGroups) const
{
Group_const_sptr productGroup = boost::make_shared<const Group>(*(factorGroups.front()));

for(size_t i = 1; i < factorGroups.size(); ++i) {
productGroup = productGroup * factorGroups[i];
}

return productGroup;
}


} // namespace Geometry
} // namespace Mantid
89 changes: 89 additions & 0 deletions Code/Mantid/Framework/Geometry/test/ProductGroupTest.h
@@ -0,0 +1,89 @@
#ifndef MANTID_GEOMETRY_PRODUCTGROUPTEST_H_
#define MANTID_GEOMETRY_PRODUCTGROUPTEST_H_

#include <cxxtest/TestSuite.h>

#include "MantidGeometry/Crystal/ProductGroup.h"
#include "MantidGeometry/Crystal/CyclicGroup.h"
#include "MantidGeometry/Crystal/SymmetryOperationFactory.h"

using namespace Mantid::Geometry;

class ProductGroupTest : public CxxTest::TestSuite
{
public:
// This pair of boilerplate methods prevent the suite being created statically
// This means the constructor isn't called when running other tests
static ProductGroupTest *createSuite() { return new ProductGroupTest(); }
static void destroySuite( ProductGroupTest *suite ) { delete suite; }


void testStringConstructor()
{
TS_ASSERT_THROWS_NOTHING(ProductGroup group("x,y,z"));

TS_ASSERT_THROWS_ANYTHING(ProductGroup group("x,y,z; doesnt work"));
TS_ASSERT_THROWS_ANYTHING(ProductGroup group("x,y,z| z,x,y"));
}

void testVectorConstructor()
{
std::vector<Group_const_sptr> groups;
groups.push_back(GroupFactory::create<CyclicGroup>("-x,-y,-z"));
groups.push_back(GroupFactory::create<CyclicGroup>("x,-y,z"));

TS_ASSERT_THROWS_NOTHING(ProductGroup group(groups));

Group_const_sptr null;
groups.push_back(null);

TS_ASSERT_THROWS_ANYTHING(ProductGroup group(groups));
}

void testGetGeneratedGroup()
{
TestableProductGroup group;

Group_const_sptr generatedGroup = group.getGeneratedGroup("-x,-y,-z; x,-y,z");

// Inversion generates 1, -1; Mirror 1, m [010] -> results in 1, -1, m [010], 2 [010]
TS_ASSERT_EQUALS(generatedGroup->order(), 4);
}

void testGetFactorGroups()
{
TestableProductGroup group;

std::vector<SymmetryOperation> symmetryOperations = SymmetryOperationFactory::Instance().createSymOps("-x,-y,-z; x,-y,z");
std::vector<Group_const_sptr> generatedGroup = group.getFactorGroups(symmetryOperations);
// one group for each symmetry operation
TS_ASSERT_EQUALS(generatedGroup.size(), 2);
}

void testGetProductGroup()
{
TestableProductGroup group;

std::vector<Group_const_sptr> groups;
groups.push_back(GroupFactory::create<CyclicGroup>("-x,-y,-z"));
groups.push_back(GroupFactory::create<CyclicGroup>("x,-y,z"));

Group_const_sptr productGroup = group.getProductGroup(groups);

TS_ASSERT_EQUALS(productGroup->order(), 4);
}

private:
class TestableProductGroup : public ProductGroup
{
friend class ProductGroupTest;
public:
TestableProductGroup() :
ProductGroup("x,y,z") { }
~TestableProductGroup() { }
};

};


#endif /* MANTID_GEOMETRY_PRODUCTGROUPTEST_H_ */

0 comments on commit e293a31

Please sign in to comment.