Skip to content

Commit

Permalink
Refs #10282. Changed IScatterer interface, added factory
Browse files Browse the repository at this point in the history
IScatterer now inherits from PropertyManager. There's now also a factory for consistent creation of scatterers.
  • Loading branch information
Michael Wedel committed Oct 26, 2014
1 parent 1672ac5 commit 0b6ba9a
Show file tree
Hide file tree
Showing 14 changed files with 583 additions and 211 deletions.
3 changes: 3 additions & 0 deletions Code/Mantid/Framework/Geometry/CMakeLists.txt
Expand Up @@ -17,6 +17,7 @@ set ( SRC_FILES
src/Crystal/ReducedCell.cpp
src/Crystal/ReflectionCondition.cpp
src/Crystal/ScalarUtils.cpp
src/Crystal/ScattererFactory.cpp
src/Crystal/SpaceGroup.cpp
src/Crystal/SpaceGroupFactory.cpp
src/Crystal/SymmetryOperation.cpp
Expand Down Expand Up @@ -131,6 +132,7 @@ set ( INC_FILES
inc/MantidGeometry/Crystal/ReducedCell.h
inc/MantidGeometry/Crystal/ReflectionCondition.h
inc/MantidGeometry/Crystal/ScalarUtils.h
inc/MantidGeometry/Crystal/ScattererFactory.h
inc/MantidGeometry/Crystal/SpaceGroup.h
inc/MantidGeometry/Crystal/SpaceGroupFactory.h
inc/MantidGeometry/Crystal/SymmetryOperation.h
Expand Down Expand Up @@ -300,6 +302,7 @@ set ( TEST_FILES
RulesTest.h
RulesUnionTest.h
ScalarUtilsTest.h
ScattererFactoryTest.h
ShapeFactoryTest.h
SpaceGroupFactoryTest.h
SpaceGroupTest.h
Expand Down
@@ -1,5 +1,5 @@
#ifndef MANTID_GEOMETRY_SCATTERERCOLLECTION_H_
#define MANTID_GEOMETRY_SCATTERERCOLLECTION_H_
#ifndef MANTID_GEOMETRY_COMPOSITESCATTERER_H_
#define MANTID_GEOMETRY_COMPOSITESCATTERER_H_

#include "MantidGeometry/DllConfig.h"
#include "MantidGeometry/Crystal/IScatterer.h"
Expand Down Expand Up @@ -27,6 +27,11 @@ namespace Geometry
are summed. Contained scatterers may be CompositeScatterers themselves,
so it's possible to build up elaborate structures.
There are two ways of creating instances of CompositeScatterer. The first
possibility is to use IScattererFactory, just like for other implementations
of IScatterer. Additionally there is a static method CompositeScatterer::create,
which creates a composite scatterer of the supplied vector of scatterers.
@author Michael Wedel, Paul Scherrer Institut - SINQ
@date 21/10/2014
Expand Down Expand Up @@ -63,11 +68,9 @@ class MANTID_GEOMETRY_DLL CompositeScatterer : public IScatterer
static CompositeScatterer_sptr create();
static CompositeScatterer_sptr create(const std::vector<IScatterer_sptr> &scatterers);

std::string name() const { return "CompositeScatterer"; }
IScatterer_sptr clone() const;

void setCell(const UnitCell &cell);
void setSpaceGroup(const SpaceGroup_const_sptr &spaceGroup);

void addScatterer(const IScatterer_sptr &scatterer);
size_t nScatterers() const;
IScatterer_sptr getScatterer(size_t i) const;
Expand All @@ -76,6 +79,9 @@ class MANTID_GEOMETRY_DLL CompositeScatterer : public IScatterer
StructureFactor calculateStructureFactor(const Kernel::V3D &hkl) const;

protected:
void afterScattererPropertySet(const std::string &propertyName);
void propagateProperty(const std::string &propertyName);

void setCommonProperties(IScatterer_sptr &scatterer);

std::vector<IScatterer_sptr> m_scatterers;
Expand All @@ -86,4 +92,4 @@ class MANTID_GEOMETRY_DLL CompositeScatterer : public IScatterer
} // namespace Geometry
} // namespace Mantid

#endif /* MANTID_GEOMETRY_SCATTERERCOLLECTION_H_ */
#endif /* MANTID_GEOMETRY_COMPOSITESCATTERER_H_ */
Expand Up @@ -21,24 +21,26 @@ typedef std::complex<double> StructureFactor;

/** IScatterer
General interface for any kind of scatterer. Position is expected to
be set as fractional coordinates with respect to the crystal axes.
IScatterer is a general interface for representing scatterers
in the unit cell of a periodic structure. Since there are many possibilities
of modelling scatterers, IScatterer is derived from PropertyManager.
This way, new scatterers with very different parameters can be
added easily.
In IScatterer, three basic properties are defined: Position, UnitCell
and SpaceGroup. Setting these properties is only possible through
the setProperty and setPropertyValue methods inherited from
PropertyManager. For retrieval there are however specialized methods,
since UnitCell and SpaceGroup properties are currently only stored
as strings.
New implementations must override the declareProperties method and
define any parameters there. It is called by the initialize method.
Currently there are two implementations of this interface, IsotropicAtomScatterer
and CompositeScatterer (composite pattern).
Most of the interface serves the purpose of providing necessary
infrastructure for calculating structure factors. This includes
information about unit cell and space group, as well as position
of the scatterer in the cell.
Please note the default behavior of the methods setPosition and setSpaceGroup.
When either of them is called, the equivalent positions are recalculated. For
more information on how this is done, please consult the documentation
of SpaceGroup.
and CompositeScatterer (composite pattern) - especially the latter
provides a good example on how to define new properties for a scatterer.
If no space group is set, or it's P1, only one "equivalent" position is
generated - the position itself.
Construction of concrete scatterers is done through ScattererFactory.
@author Michael Wedel, Paul Scherrer Institut - SINQ
@date 20/10/2014
Expand Down Expand Up @@ -71,11 +73,13 @@ typedef boost::shared_ptr<IScatterer> IScatterer_sptr;
class MANTID_GEOMETRY_DLL IScatterer : public Kernel::PropertyManager
{
public:
IScatterer(const Kernel::V3D &position = Kernel::V3D(0.0, 0.0, 0.0));
IScatterer();
virtual ~IScatterer() { }

void initialize();
bool isInitialized();

virtual std::string name() const = 0;
virtual IScatterer_sptr clone() const = 0;

Kernel::V3D getPosition() const;
Expand All @@ -90,17 +94,32 @@ class MANTID_GEOMETRY_DLL IScatterer : public Kernel::PropertyManager
virtual void setCell(const UnitCell &cell);
virtual void setSpaceGroup(const SpaceGroup_const_sptr &spaceGroup);

void afterPropertySet(const std::string &propertyName);

/// Base implementation does nothing - for implementing classes only.
virtual void declareProperties() { }

/// This method should be re-implemented by subclasses for additional parameter processing.
virtual void afterScattererPropertySet(const std::string &) { }

void recalculateEquivalentPositions();

Kernel::V3D m_position;
std::vector<Kernel::V3D> m_equivalentPositions;

UnitCell m_cell;
SpaceGroup_const_sptr m_spaceGroup;

bool m_isInitialized;
};

/**
* Helper class for validating unit cell strings.
*
* This validator checks whether a string consists of either 3 or 6 numbers,
* possibly floating point numbers. It's required for the unit cell string
* property.
*/
class MANTID_GEOMETRY_DLL UnitCellStringValidator : public Kernel::TypedValidator<std::string>
{
protected:
Expand Down
Expand Up @@ -58,9 +58,10 @@ namespace Geometry
Fm-3m, Cu atoms occupy the position (0,0,0) and, because of the F-centering,
also 3 additional positions.
IScatterer_sptr cu = IsotropicAtomScatterer::create("Cu", V3D(0, 0, 0));
cu->setSpaceGroup(spaceGroupCu);
cu->setCell(cellCu)
IScatterer_sptr cu = ScattererFactory::Instance().createScatterer(
"IsotropicAtomScatterer",
"Element=Cu; SpaceGroup=F m -3 m")
cu->setProperty("UnitCell", unitCellToStr(cellCu));
StructureFactor F = cu->calculateStructureFactor(V3D(1, 1, 1));
Expand Down Expand Up @@ -100,38 +101,31 @@ typedef boost::shared_ptr<IsotropicAtomScatterer> IsotropicAtomScatterer_sptr;
class MANTID_GEOMETRY_DLL IsotropicAtomScatterer : public IScatterer
{
public:
IsotropicAtomScatterer(const std::string &element,
const Kernel::V3D &position,
double U = 0.0, double occupancy = 1.0);
IsotropicAtomScatterer();
virtual ~IsotropicAtomScatterer() { }

static IsotropicAtomScatterer_sptr create(const std::string &element,
const Kernel::V3D &position,
double U = 0.0, double occupancy = 1.0);

std::string name() const { return "IsotropicAtomScatterer"; }
IScatterer_sptr clone() const;

void setElement(const std::string &element);
std::string getElement() const;
PhysicalConstants::NeutronAtom getNeutronAtom() const;

void setOccupancy(double occupancy);
double getOccupancy() const;

void setU(double U);
double getU() const;

StructureFactor calculateStructureFactor(const Kernel::V3D &hkl) const;

protected:
void setElement(const std::string &element);

void declareProperties();
void afterScattererPropertySet(const std::string &propertyName);

double getDebyeWallerFactor(const Kernel::V3D &hkl) const;
double getScatteringLength() const;

PhysicalConstants::NeutronAtom m_atom;
std::string m_label;

double m_occupancy;
double m_U;
};

typedef boost::shared_ptr<IsotropicAtomScatterer> IsotropicAtomScatterer_sptr;
Expand Down
@@ -0,0 +1,103 @@
#ifndef MANTID_GEOMETRY_SCATTERERFACTORY_H_
#define MANTID_GEOMETRY_SCATTERERFACTORY_H_

#include "MantidGeometry/DllConfig.h"
#include "MantidKernel/DynamicFactory.h"
#include "MantidKernel/SingletonHolder.h"
#include "MantidGeometry/Crystal/IScatterer.h"

namespace Mantid
{
namespace Geometry
{

/** ScattererFactory :
This class implements a factory for concrete IScatterer classes.
When a new scatterer is derived from IScatterer, it should be registered
in the factory. Like other factories in Mantid, a macro is provided for
this purpose:
DECLARE_SCATTERER(NewScattererClass)
At runtime, instances of this class can be created like this:
IScatterer_sptr scatterer = ScattererFactory::Instance().createScatterer("NewScattererClass");
The returned object is initialized, which is required for using the
Kernel::Property-based system of setting parameters for the scatterer.
To make creation of scatterers more convenient, it's possible to provide
a string with "name=value" pairs, separated by semi-colons, which assigns
property values. This is similar to the way FunctionFactory::createInitialized works:
IScatterer_sptr s = ScattererFactory::Instance()
.createScatterer(
"NewScatterer",
"SpaceGroup=F m -3 m; Position=[0.1,0.2,0.3]");
If you choose to use the raw create/createUnwrapped methods, you have to
make sure to call IScatterer::initialize() on the created instance.
@author Michael Wedel, Paul Scherrer Institut - SINQ
@date 26/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 ScattererFactoryImpl : public Kernel::DynamicFactory<IScatterer>
{
public:
IScatterer_sptr createScatterer(const std::string &name, const std::string &properties = "");

/// Subscribes a scatterer class into the factory.
template<class C>
void subscribeScatterer()
{
Kernel::Instantiator<C, IScatterer> *instantiator = new Kernel::Instantiator<C, IScatterer>;
IScatterer_sptr scatterer = instantiator->createInstance();

subscribe(scatterer->name(), instantiator);
}

private:
friend struct Mantid::Kernel::CreateUsingNew<ScattererFactoryImpl>;

ScattererFactoryImpl();
};

// This is taken from FuncMinimizerFactory
#ifdef _WIN32
template class MANTID_GEOMETRY_DLL Mantid::Kernel::SingletonHolder<ScattererFactoryImpl>;
#endif

typedef Mantid::Kernel::SingletonHolder<ScattererFactoryImpl> ScattererFactory;


} // namespace Geometry
} // namespace Mantid

#define DECLARE_SCATTERER(classname) \
namespace { \
Mantid::Kernel::RegistrationHelper register_scatterer_##classname( \
((Mantid::Geometry::ScattererFactory::Instance().subscribeScatterer<classname>()) \
, 0)); \
}

#endif /* MANTID_GEOMETRY_ISCATTERERFACTORY_H_ */

0 comments on commit 0b6ba9a

Please sign in to comment.