diff --git a/Code/Mantid/Framework/Kernel/inc/MantidKernel/Unit.h b/Code/Mantid/Framework/Kernel/inc/MantidKernel/Unit.h index 82d5494cdd3110a2db6e620a012dab4049c60d98..0bbd6ce88c505a00aebabc6949cf31335c539ae5 100644 --- a/Code/Mantid/Framework/Kernel/inc/MantidKernel/Unit.h +++ b/Code/Mantid/Framework/Kernel/inc/MantidKernel/Unit.h @@ -160,6 +160,9 @@ protected: // Add a 'quick conversion' for a unit pair void addConversion(std::string to, const double& factor, const double& power = 1.0) const; + /// Removes all registered 'quick conversions' + void clearConversions() const; + /// The unit values have been initialized bool initialized; /// l1 :: The source-sample distance (in metres) @@ -506,6 +509,49 @@ protected: bool do_sfpFrom; ///< Apply the sfpFrom value }; +//================================================================================================= +/// SpinEchoLength in nm +class MANTID_KERNEL_DLL SpinEchoLength : public Wavelength +{ +public: + const std::string unitID() const; ///< "SpinEchoLength" + const std::string caption() const { return "Spin Echo Length"; } + const std::string label() const {return "nm"; } + + virtual double singleToTOF(const double x) const; + virtual double singleFromTOF(const double tof) const; + virtual void init(); + virtual Unit * clone() const; + + /// Constructor + SpinEchoLength(); + /// Destructor + ~SpinEchoLength() {} + +}; + +//================================================================================================= +/// SpinEchoTime in ns +class MANTID_KERNEL_DLL SpinEchoTime : public Wavelength +{ +public: + const std::string unitID() const; ///< "SpinEchoTime" + const std::string caption() const { return "Spin Echo Time"; } + const std::string label() const {return "ns"; } + + virtual double singleToTOF(const double x) const; + virtual double singleFromTOF(const double tof) const; + virtual void init(); + virtual Unit * clone() const; + + /// Constructor + SpinEchoTime(); + /// Destructor + ~SpinEchoTime() {} + +}; + + } // namespace Units } // namespace Kernel diff --git a/Code/Mantid/Framework/Kernel/src/Unit.cpp b/Code/Mantid/Framework/Kernel/src/Unit.cpp index e037ff233ab0f79cb85d0f22eb64d8f61be532fb..78e8c80f2e5c989c9b6c479671553f34d7578247 100644 --- a/Code/Mantid/Framework/Kernel/src/Unit.cpp +++ b/Code/Mantid/Framework/Kernel/src/Unit.cpp @@ -87,6 +87,14 @@ void Unit::addConversion(std::string to, const double& factor, const double& pow } } +//--------------------------------------------------------------------------------------- +/** Removes all registered 'quick conversions' from the unit class on which this method is called. + */ +void Unit::clearConversions() const +{ + s_conversionFactors.clear(); +} + //--------------------------------------------------------------------------------------- /** Initialize the unit to perform conversion using singleToTof() and singleFromTof() * @@ -870,6 +878,93 @@ Unit * Momentum::clone() const } + +// ============================================================================================ +/* SpinEchoLength + * =================================================================================================== + * + * Delta = (constant)*(wavelength)^2 + */ +DECLARE_UNIT(SpinEchoLength) + +SpinEchoLength::SpinEchoLength() : Wavelength() +{ + clearConversions(); +} + +void SpinEchoLength::init() +{ + // Efixed must be set to something + if (efixed == 0.0) throw std::invalid_argument("efixed must be set for spin echo length calculation"); + if (emode > 0) + { + throw std::invalid_argument("emode must be equal to 0 for spin echo length calculation"); + } + Wavelength::init(); +} + +double SpinEchoLength::singleToTOF(const double x) const +{ + double wavelength = sqrt(x/efixed); + double tof = Wavelength::singleToTOF(wavelength); + return tof; +} + +double SpinEchoLength::singleFromTOF(const double tof) const +{ + double wavelength = Wavelength::singleFromTOF(tof); + double x = efixed * wavelength * wavelength; + return x; +} + +Unit * SpinEchoLength::clone() const +{ + return new SpinEchoLength(*this); +} + +// ============================================================================================ +/* SpinEchoTime + * =================================================================================================== + * + * Tau = (constant)*(wavelength)^3 + */ +DECLARE_UNIT(SpinEchoTime) + +SpinEchoTime::SpinEchoTime() : Wavelength() +{ + clearConversions(); +} + +void SpinEchoTime::init() +{ + // Efixed must be set to something + if (efixed == 0.0) throw std::invalid_argument("efixed must be set for spin echo time calculation"); + if (emode > 0) + { + throw std::invalid_argument("emode must be equal to 0 for spin echo time calculation"); + } + Wavelength::init(); +} + +double SpinEchoTime::singleToTOF(const double x) const +{ + double wavelength = pow(x/efixed,1.0/3.0); + double tof = Wavelength::singleToTOF(wavelength); + return tof; +} + +double SpinEchoTime::singleFromTOF(const double tof) const +{ + double wavelength = Wavelength::singleFromTOF(tof); + double x = efixed * wavelength * wavelength * wavelength; + return x; +} + +Unit * SpinEchoTime::clone() const +{ + return new SpinEchoTime(*this); +} + } // namespace Units } // namespace Kernel diff --git a/Code/Mantid/Framework/Kernel/test/UnitTest.h b/Code/Mantid/Framework/Kernel/test/UnitTest.h index 8650bb803d7588d8ea657179349778f354fb9dd4..23ac2e72b5e4006491f0f6caf28e04f8062a581e 100644 --- a/Code/Mantid/Framework/Kernel/test/UnitTest.h +++ b/Code/Mantid/Framework/Kernel/test/UnitTest.h @@ -712,6 +712,133 @@ public: } + //---------------------------------------------------------------------- + // Spin Echo Length tests + //---------------------------------------------------------------------- + + void testSpinEchoLength_unitID() + { + TS_ASSERT_EQUALS( delta.unitID(), "SpinEchoLength" ) + } + + void testSpinEchoLength_caption() + { + TS_ASSERT_EQUALS( delta.caption(), "Spin Echo Length" ) + } + + void testSpinEchoLength_label() + { + TS_ASSERT_EQUALS( delta.label(), "nm" ) + } + + void testSpinEchoLength_cast() + { + Unit *u = NULL; + TS_ASSERT_THROWS_NOTHING( u = dynamic_cast<Unit*>(&delta) ); + TS_ASSERT_EQUALS(u->unitID(), "SpinEchoLength"); + } + + void testSpinEchoLength_toTOF() + { + std::vector<double> x(1, 4.5), y(1, 1.5); + std::vector<double> yy = y; + TS_ASSERT_THROWS_NOTHING( delta.toTOF(x,y,1.0,1.0,1.0,0,2.0,1.0) ) + TS_ASSERT_DELTA( x[0], 758.3352, 0.0001 ) + TS_ASSERT( yy == y ) + + TS_ASSERT_DELTA( delta.convertSingleToTOF(4.5, 1.0,1.0,1.0,0,2.0,1.0), 758.3352, 0.0001 ); + } + + void testSpinEchoLength_fromTOF() + { + std::vector<double> x(1, 1000.5), y(1, 1.5); + std::vector<double> yy = y; + TS_ASSERT_THROWS_NOTHING( delta.fromTOF(x,y,1.0,1.0,1.0,0,2.0,1.0) ) + TS_ASSERT_DELTA( x[0], 7.8329, 0.0001 ) + TS_ASSERT( yy == y ) + + TS_ASSERT_DELTA( delta.convertSingleFromTOF(1000.5, 1.0,1.0,1.0,0,2.0,1.0), 7.8329, 0.0001); + } + + void testSpinEchoLength_invalidfromTOF() + { + std::vector<double> x(1, 1000.5), y(1, 1.5); + //emode must = 0 + TS_ASSERT_THROWS_ANYTHING( delta.fromTOF(x,y,1.0,1.0,1.0,1,2.0,1.0) ) + } + + void testSpinEchoLength_quickConversions() + { + // Test that the quick conversions from wavelength have not leaked through + double factor, power; + TS_ASSERT( !delta.quickConversion(energy,factor,power) ) + TS_ASSERT( !delta.quickConversion(energyk,factor,power) ) + } + + + //---------------------------------------------------------------------- + // Spin Echo Time tests + //---------------------------------------------------------------------- + + void testSpinEchoTime_unitID() + { + TS_ASSERT_EQUALS( tau.unitID(), "SpinEchoTime" ) + } + + void testSpinEchoTime_caption() + { + TS_ASSERT_EQUALS( tau.caption(), "Spin Echo Time" ) + } + + void testSpinEchoTime_label() + { + TS_ASSERT_EQUALS( tau.label(), "ns" ) + } + + void testSpinEchoTime_cast() + { + Unit *u = NULL; + TS_ASSERT_THROWS_NOTHING( u = dynamic_cast<Unit*>(&tau) ); + TS_ASSERT_EQUALS(u->unitID(), "SpinEchoTime"); + } + + void testSpinEchoTime_toTOF() + { + std::vector<double> x(1, 4.5), y(1, 1.5); + std::vector<double> yy = y; + TS_ASSERT_THROWS_NOTHING( tau.toTOF(x,y,1.0,1.0,1.0,0,2.0,1.0) ) + TS_ASSERT_DELTA( x[0], 662.4668, 0.0001 ) + TS_ASSERT( yy == y ) + + TS_ASSERT_DELTA( tau.convertSingleToTOF(4.5, 1.0,1.0,1.0,0,2.0,1.0), 662.4668, 0.0001 ); + } + + void testSpinEchoTime_fromTOF() + { + std::vector<double> x(1, 1000.5), y(1, 1.5); + std::vector<double> yy = y; + TS_ASSERT_THROWS_NOTHING( tau.fromTOF(x,y,1.0,1.0,1.0,0,2.0,1.0) ) + TS_ASSERT_DELTA( x[0], 15.5014, 0.0001 ) + TS_ASSERT( yy == y ) + + TS_ASSERT_DELTA( tau.convertSingleFromTOF(1000.5, 1.0,1.0,1.0,0,2.0,1.0), 15.5014, 0.0001); + } + + void testSpinEchoTime_invalidfromTOF() + { + std::vector<double> x(1, 1000.5), y(1, 1.5); + //emode must = 0 + TS_ASSERT_THROWS_ANYTHING( tau.fromTOF(x,y,1.0,1.0,1.0,1,2.0,1.0) ) + } + + void testSpinEchoTime_quickConversions() + { + // Test that the quick conversions from wavelength have not leaked through + double factor, power; + TS_ASSERT( !tau.quickConversion(energy,factor,power) ) + TS_ASSERT( !tau.quickConversion(energyk,factor,power) ) + } + private: Units::TOF tof; Units::Wavelength lambda; @@ -723,6 +850,8 @@ private: Units::DeltaE dE; Units::DeltaE_inWavenumber dEk; Units::Momentum k_i; + Units::SpinEchoLength delta; + Units::SpinEchoTime tau; }; #endif /*UNITTEST_H_*/