From 8b2e37d4eb4693c6e3c59f5d1e2b9e642246a67f Mon Sep 17 00:00:00 2001 From: Walter Van Herck <w.van.herck@fz-juelich.de> Date: Fri, 9 Aug 2013 17:34:36 +0200 Subject: [PATCH] Added polarized functionality to LayerStrategyBuilder and DecouplingApproximationStrategy --- .../inc/IInterferenceFunctionStrategy.h | 1 + Core/Algorithms/inc/LayerStrategyBuilder.h | 5 ++ .../src/DecouplingApproximationStrategy.cpp | 31 +++++-- Core/Algorithms/src/LayerStrategyBuilder.cpp | 90 +++++++++++++++---- Core/FormFactors/inc/FormFactors.h | 1 + Core/Tools/inc/MathFunctions.h | 13 +++ 6 files changed, 117 insertions(+), 24 deletions(-) diff --git a/Core/Algorithms/inc/IInterferenceFunctionStrategy.h b/Core/Algorithms/inc/IInterferenceFunctionStrategy.h index 9d9f0e54f1b..8fac942d3af 100644 --- a/Core/Algorithms/inc/IInterferenceFunctionStrategy.h +++ b/Core/Algorithms/inc/IInterferenceFunctionStrategy.h @@ -21,6 +21,7 @@ #include "Bin.h" #include "SafePointerVector.h" #include "LayerStrategyBuilder.h" +#include "FormFactorDWBAPol.h" #include <vector> diff --git a/Core/Algorithms/inc/LayerStrategyBuilder.h b/Core/Algorithms/inc/LayerStrategyBuilder.h index c23948bbc28..adc1f7e81b6 100644 --- a/Core/Algorithms/inc/LayerStrategyBuilder.h +++ b/Core/Algorithms/inc/LayerStrategyBuilder.h @@ -73,6 +73,11 @@ private: const ParticleInfo *p_particle_info, const IMaterial *p_ambient_material, complex_t factor) const; + //! Creates formfactor info for single particle in presence of polarization + FormFactorInfo *createFormFactorInfoPol( + const ParticleInfo *p_particle_info, + const IMaterial *p_ambient_material, + complex_t factor) const; SafePointerVector<FormFactorInfo> m_ff_infos; SafePointerVector<IInterferenceFunction> m_ifs; diff --git a/Core/Algorithms/src/DecouplingApproximationStrategy.cpp b/Core/Algorithms/src/DecouplingApproximationStrategy.cpp index c95771f9fdf..a94a538a6e5 100644 --- a/Core/Algorithms/src/DecouplingApproximationStrategy.cpp +++ b/Core/Algorithms/src/DecouplingApproximationStrategy.cpp @@ -15,6 +15,8 @@ #include "DecouplingApproximationStrategy.h" #include "Exceptions.h" +#include "MathFunctions.h" + #include <cassert> #include <iostream> @@ -63,15 +65,26 @@ Eigen::Matrix2d DecouplingApproximationStrategy::evaluatePol( const Bin1DCVector& k_f2_bin, double alpha_i, double alpha_f, double phi_f) const { - (void)k_i; - (void)k_f1_bin; - (void)k_f2_bin; - (void)alpha_i; - (void)alpha_f; - (void)phi_f; - throw Exceptions::NotImplementedException( - "DecouplingApproximationStrategy::evaluatePol: " - "this strategy is not implemented for magnetic systems"); + Eigen::Matrix2d intensity = Eigen::Matrix2d::Zero(); + Eigen::Matrix2cd amplitude = Eigen::Matrix2cd::Zero(); + for (size_t i=0; i<m_ff_infos.size(); ++i) { + FormFactorDWBAPol *p_ff_pol = dynamic_cast<FormFactorDWBAPol *>( + m_ff_infos[i]->mp_ff); + if (!p_ff_pol) { + throw Exceptions::ClassInitializationException( + "DecouplingApproximationStrategy::evaluatePol: " + "unpolarized form factor encountered"); + } + Eigen::Matrix2cd ff = p_ff_pol->evaluatePol(k_i, k_f1_bin, k_f2_bin, + alpha_i, alpha_f, phi_f); + + double fraction = m_ff_infos[i]->m_abundance; + amplitude += fraction*ff; + intensity += fraction*(MathFunctions::Norm(ff)); + } + Eigen::Matrix2d amplitude_norm = MathFunctions::Norm(amplitude); + double itf_function = m_ifs[0]->evaluate(k_i-k_f1_bin.getMidPoint()); + return intensity + amplitude_norm*(itf_function-1.0); } bool DecouplingApproximationStrategy::checkVectorSizes() const diff --git a/Core/Algorithms/src/LayerStrategyBuilder.cpp b/Core/Algorithms/src/LayerStrategyBuilder.cpp index f90af0d98ea..510f9543197 100644 --- a/Core/Algorithms/src/LayerStrategyBuilder.cpp +++ b/Core/Algorithms/src/LayerStrategyBuilder.cpp @@ -25,6 +25,7 @@ #include "PositionParticleInfo.h" #include <cmath> +#include <boost/scoped_ptr.hpp> LayerStrategyBuilder::LayerStrategyBuilder( const Layer& decorated_layer, const Simulation& simulation, @@ -126,9 +127,15 @@ void LayerStrategyBuilder::collectFormFactorInfos() 0; particle_index<number_of_particles; ++particle_index) { const ParticleInfo *p_particle_info = p_decoration->getParticleInfo(particle_index); - FormFactorInfo *p_ff_info = - createFormFactorInfo(p_particle_info, p_layer_material, - wavevector_scattering_factor); + FormFactorInfo *p_ff_info; + if (mp_magnetic_coeff_map) { + p_ff_info = createFormFactorInfoPol(p_particle_info, + p_layer_material, wavevector_scattering_factor); + } + else { + p_ff_info = createFormFactorInfo(p_particle_info, p_layer_material, + wavevector_scattering_factor); + } p_ff_info->m_abundance = p_decoration->getAbundanceFractionOfParticle(particle_index); m_ff_infos.push_back(p_ff_info); @@ -159,25 +166,21 @@ FormFactorInfo *LayerStrategyBuilder::createFormFactorInfo( complex_t factor) const { FormFactorInfo *p_result = new FormFactorInfo; - Particle *p_particle_clone = p_particle_info->getParticle()->clone(); + boost::scoped_ptr<Particle> P_particle_clone(p_particle_info->getParticle()->clone()); const Geometry::PTransform3D transform = p_particle_info->getPTransform3D(); // formfactor - p_particle_clone->setAmbientMaterial(p_ambient_material); - IFormFactor *ff_particle = p_particle_clone->createFormFactor(); - delete p_particle_clone; - IFormFactor *ff_transformed(0); + P_particle_clone->setAmbientMaterial(p_ambient_material); + IFormFactor *ff_particle = P_particle_clone->createFormFactor(); + IFormFactor *ff_transformed(ff_particle); if(transform) { ff_transformed = new FormFactorDecoratorTransformation(ff_particle, transform); - } else{ - ff_transformed = ff_particle; } - IFormFactor *p_ff_framework(0); + IFormFactor *p_ff_framework(ff_transformed); switch (m_sim_params.me_framework) { case SimulationParameters::BA: // Born Approximation - p_ff_framework = ff_transformed; break; case SimulationParameters::DWBA: // Distorted Wave Born Approximation { @@ -195,8 +198,10 @@ FormFactorInfo *LayerStrategyBuilder::createFormFactorInfo( default: throw Exceptions::RuntimeErrorException("Framework must be BA or DWBA"); } - FormFactorDecoratorFactor *p_ff = - new FormFactorDecoratorFactor(p_ff_framework, factor); + IFormFactor *p_ff(p_ff_framework); + if ( factor != complex_t(1.0, 0.0) ) { + p_ff = new FormFactorDecoratorFactor(p_ff_framework, factor); + } p_result->mp_ff = p_ff; // Other info (position and abundance const PositionParticleInfo *p_pos_particle_info = @@ -210,6 +215,62 @@ FormFactorInfo *LayerStrategyBuilder::createFormFactorInfo( return p_result; } +FormFactorInfo* LayerStrategyBuilder::createFormFactorInfoPol( + const ParticleInfo* p_particle_info, + const IMaterial* p_ambient_material, complex_t factor) const +{ + FormFactorInfo *p_result = new FormFactorInfo; + boost::scoped_ptr<Particle> P_particle_clone(p_particle_info-> + getParticle()->clone()); + const Geometry::PTransform3D transform = p_particle_info->getPTransform3D(); + const IMaterial *p_material = P_particle_clone->getMaterial(); + + // formfactor + IFormFactor *ff_particle = P_particle_clone->getSimpleFormFactor()->clone(); + IFormFactor *ff_particle_factor(ff_particle); + if ( factor!=complex_t(1.0,0.0) ) { + ff_particle_factor = new FormFactorDecoratorFactor(ff_particle, factor); + } + IFormFactor *ff_transformed(ff_particle_factor); + if(transform) { + ff_transformed = new FormFactorDecoratorTransformation( + ff_particle_factor, transform); + } + IFormFactor *p_ff_framework(ff_transformed); + switch (m_sim_params.me_framework) + { + case SimulationParameters::BA: // Born Approximation + break; + case SimulationParameters::DWBA: // Distorted Wave Born Approximation + { + if (!mp_magnetic_coeff_map) { + throw Exceptions::ClassInitializationException( + "Magnetic coefficients are necessary for DWBA"); + } + FormFactorDWBAPol *p_dwba_ff_pol = + new FormFactorDWBAPol(ff_transformed); + p_dwba_ff_pol->setRTInfo(*mp_magnetic_coeff_map); + p_dwba_ff_pol->setMaterial(p_material); + p_dwba_ff_pol->setAmbientMaterial(p_ambient_material); + p_ff_framework = p_dwba_ff_pol; + break; + } + default: + throw Exceptions::RuntimeErrorException("Framework must be BA or DWBA"); + } + p_result->mp_ff = p_ff_framework; + // Other info (position and abundance) + const PositionParticleInfo *p_pos_particle_info = + dynamic_cast<const PositionParticleInfo *>(p_particle_info); + if (p_pos_particle_info) { + kvector_t position = p_pos_particle_info->getPosition(); + p_result->m_pos_x = position.x(); + p_result->m_pos_y = position.y(); + } + p_result->m_abundance = p_particle_info->getAbundance(); + return p_result; +} + // ============================================================================= // Implementation of FormFactorInfo // ============================================================================= @@ -226,4 +287,3 @@ FormFactorInfo* FormFactorInfo::clone() const return p_result; } - diff --git a/Core/FormFactors/inc/FormFactors.h b/Core/FormFactors/inc/FormFactors.h index 2308ab39deb..9c3e92910ab 100644 --- a/Core/FormFactors/inc/FormFactors.h +++ b/Core/FormFactors/inc/FormFactors.h @@ -28,6 +28,7 @@ #include "FormFactorDecoratorTransformation.h" #include "FormFactorDWBA.h" #include "FormFactorDWBAConstZ.h" +#include "FormFactorDWBAPol.h" #include "FormFactorEllipsoid.h" #include "FormFactorFullSphere.h" #include "FormFactorFullSpheroid.h" diff --git a/Core/Tools/inc/MathFunctions.h b/Core/Tools/inc/MathFunctions.h index 86ff5ebe5ad..fa4ab8ed66d 100644 --- a/Core/Tools/inc/MathFunctions.h +++ b/Core/Tools/inc/MathFunctions.h @@ -29,6 +29,8 @@ #include "gsl/gsl_sf_expint.h" #include "gsl/gsl_integration.h" +#include <Eigen/Core> + //! Various mathematical functions. namespace MathFunctions @@ -85,6 +87,8 @@ complex_t FastCos(const complex_t &x); //! simultaneous complex sine and cosine calculations void FastSinCos(const complex_t &x, complex_t &xsin, complex_t &xcos); +Eigen::Matrix2d Norm(Eigen::Matrix2cd &M); + } // Namespace MathFunctions inline double MathFunctions::GenerateNormalRandom(double average, double std_dev) @@ -183,6 +187,15 @@ inline void MathFunctions::FastSinCos(const complex_t &x, xcos = complex_t( cosa*coshb, -sina*sinhb ); } +inline Eigen::Matrix2d MathFunctions::Norm(Eigen::Matrix2cd &M) { + Eigen::Matrix2d result; + result(0,0) = std::norm((complex_t)M(0,0)); + result(0,1) = std::norm((complex_t)M(0,1)); + result(1,0) = std::norm((complex_t)M(1,0)); + result(1,1) = std::norm((complex_t)M(1,1)); + return result; +} + #endif // MATHFUNCTIONS_H -- GitLab