diff --git a/Core/Algorithms/inc/Beam.h b/Core/Algorithms/inc/Beam.h
index 8afec34ae2578a860831f2dd969f2ef057a2ab50..11a58878050f6863441b7c1d382ab5c4f0c567b7 100644
--- a/Core/Algorithms/inc/Beam.h
+++ b/Core/Algorithms/inc/Beam.h
@@ -39,10 +39,7 @@ public:
     virtual ~Beam() {}
 
     //! Get the value of the wavevector
-    cvector_t getCentralK() const { return m_central_k; }
-
-    //! Sets the value of the incoming wavevector
-    void setCentralK(const cvector_t& k_i);
+    cvector_t getCentralK() const;
 
     //! Sets the value of the incoming wavevector in terms of wavelength
     //! and incoming angles
@@ -84,7 +81,7 @@ private:
     //! Initialize polarization (for constructors)
     void initPolarization();
 
-    cvector_t m_central_k;  //!< incoming wavevector
+    double m_lambda, m_alpha, m_phi; //!< wavelength and angles of beam
     double m_intensity;     //!< beam intensity (neutrons/sec)
 #ifndef GCCXML_SKIP_THIS
     Eigen::Matrix2cd m_polarization; //!< polarization density matrix
diff --git a/Core/Algorithms/inc/DistributionWeighter.h b/Core/Algorithms/inc/DistributionWeighter.h
new file mode 100644
index 0000000000000000000000000000000000000000..cc70bacd9411fc2af494c9adfa7c96061a421279
--- /dev/null
+++ b/Core/Algorithms/inc/DistributionWeighter.h
@@ -0,0 +1,56 @@
+// ************************************************************************** //
+//
+//  BornAgain: simulate and fit scattering at grazing incidence
+//
+//! @file      Algorithms/inc/DistributionWeighter.h
+//! @brief     Defines class DistributionWeighter.
+//!
+//! @homepage  http://apps.jcns.fz-juelich.de/BornAgain
+//! @license   GNU General Public License v3 or higher (see COPYING)
+//! @copyright Forschungszentrum Jülich GmbH 2013
+//! @authors   Scientific Computing Group at MLZ Garching
+//! @authors   C. Durniak, G. Pospelov, W. Van Herck, J. Wuttke
+//
+// ************************************************************************** //
+
+#ifndef DISTRIBUTIONWEIGHTER_H_
+#define DISTRIBUTIONWEIGHTER_H_
+
+#include "IParameterized.h"
+#include "ParameterDistribution.h"
+
+
+class IDistribution1D;
+
+//! @class DistributionWeighter
+//! @ingroup algorithms_internal
+//! @brief Provides the functionality to average over parameter distributions
+//! with weights
+class DistributionWeighter : public IParameterized
+{
+public:
+	DistributionWeighter();
+	~DistributionWeighter();
+
+	//! add a samples parameter distribution
+	void addParameterDistribution(const std::string &param_name,
+			const IDistribution1D &distribution, size_t nbr_samples,
+			double sigma_factor=0.0);
+
+	//! get the total number of parameter value combinations (product
+	//! of the individual sizes of each parameter distribution
+	size_t getTotalNumberOfSamples() const;
+
+	//! set the parameter values of the simulation object to a specific
+	//! combination of values, determined by the index (which must be smaller
+	//! than the total number of combinations) and returns the weight
+	//! associated with this combination of parameter values
+	double setParameterValues(ParameterPool *p_parameter_pool, size_t index);
+private:
+	size_t m_nbr_combinations;
+	std::vector<ParameterDistribution> m_distributions;
+	std::vector<std::vector<ParameterSample> > m_cached_samples;
+};
+
+
+#endif /* DISTRIBUTIONWEIGHTER_H_ */
diff --git a/Core/Algorithms/src/Beam.cpp b/Core/Algorithms/src/Beam.cpp
index e6c7e34197cb343995a0702c8cd1f6979d2b7d79..f549968a3bb581deb551a5474e7a05a84f538120 100644
--- a/Core/Algorithms/src/Beam.cpp
+++ b/Core/Algorithms/src/Beam.cpp
@@ -18,15 +18,20 @@
 #include <Eigen/LU>
 
 
-Beam::Beam() : m_central_k(), m_intensity(1.0)
+Beam::Beam()
+: m_lambda(1.0)
+, m_alpha(0.0)
+, m_phi(0.0)
+, m_intensity(1.0)
 {
     setName("Beam");
     init_parameters();
     initPolarization();
 }
 
-Beam::Beam(const Beam& other) : IParameterized(), m_central_k(other.m_central_k)
-  , m_intensity(other.m_intensity), m_polarization(other.m_polarization)
+Beam::Beam(const Beam& other) : IParameterized(), m_lambda(other.m_lambda),
+		m_alpha(other.m_alpha), m_phi(other.m_phi),
+		m_intensity(other.m_intensity), m_polarization(other.m_polarization)
 {
     setName(other.getName());
     init_parameters();
@@ -42,17 +47,19 @@ Beam& Beam::operator=(const Beam& other)
     return *this;
 }
 
-void Beam::setCentralK(const cvector_t& k_i)
+cvector_t Beam::getCentralK() const
 {
-    m_central_k = k_i;
+    cvector_t k;
+    k.setLambdaAlphaPhi(m_lambda, m_alpha, m_phi);
+    return k;
 }
 
 void Beam::setCentralK(double lambda, double alpha_i, double phi_i)
 {
-    cvector_t k_i;
     if (alpha_i >0) alpha_i = - alpha_i;
-    k_i.setLambdaAlphaPhi(lambda, alpha_i, phi_i);
-    m_central_k = k_i;
+    m_lambda = lambda;
+    m_alpha = alpha_i;
+    m_phi = phi_i;
 }
 
 void Beam::setPolarization(const Eigen::Matrix2cd &polarization)
@@ -91,11 +98,16 @@ void Beam::init_parameters()
 {
     clearParameterPool();
     registerParameter("intensity", &m_intensity);
+    registerParameter("wavelength", &m_lambda);
+    registerParameter("alpha", &m_alpha);
+    registerParameter("phi", &m_phi);
 }
 
 void Beam::swapContent(Beam& other)
 {
-    std::swap(this->m_central_k, other.m_central_k);
+    std::swap(this->m_lambda, other.m_lambda);
+    std::swap(this->m_alpha, other.m_alpha);
+    std::swap(this->m_phi, other.m_phi);
     std::swap(this->m_intensity, other.m_intensity);
     std::swap(this->m_polarization, other.m_polarization);
 }
@@ -106,3 +118,4 @@ void Beam::initPolarization()
     m_polarization(0,0) = 0.5;
     m_polarization(1,1) = 0.5;
 }
+
diff --git a/Core/Algorithms/src/DistributionWeighter.cpp b/Core/Algorithms/src/DistributionWeighter.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..db9c6f9a10ca8127d1fc4226b442d89e71b10c86
--- /dev/null
+++ b/Core/Algorithms/src/DistributionWeighter.cpp
@@ -0,0 +1,73 @@
+// ************************************************************************** //
+//
+//  BornAgain: simulate and fit scattering at grazing incidence
+//
+//! @file      Algorithms/src/DistributionWeighter.cpp
+//! @brief     Implements class DistributionWeighter.
+//!
+//! @homepage  http://apps.jcns.fz-juelich.de/BornAgain
+//! @license   GNU General Public License v3 or higher (see COPYING)
+//! @copyright Forschungszentrum Jülich GmbH 2013
+//! @authors   Scientific Computing Group at MLZ Garching
+//! @authors   C. Durniak, G. Pospelov, W. Van Herck, J. Wuttke
+//
+// ************************************************************************** //
+
+#include "DistributionWeighter.h"
+
+DistributionWeighter::DistributionWeighter()
+: m_nbr_combinations(1)
+{
+}
+
+DistributionWeighter::~DistributionWeighter()
+{
+}
+
+void DistributionWeighter::addParameterDistribution(
+		const std::string &param_name, const IDistribution1D &distribution,
+		size_t nbr_samples, double sigma_factor)
+{
+	if (nbr_samples > 0) {
+		ParameterDistribution par_distr(param_name);
+		par_distr.setDistribution(distribution, nbr_samples, sigma_factor);
+		m_distributions.push_back(par_distr);
+		m_nbr_combinations *= nbr_samples;
+		m_cached_samples.push_back(par_distr.generateSamples());
+	}
+}
+
+size_t DistributionWeighter::getTotalNumberOfSamples() const
+{
+	return m_nbr_combinations;
+}
+
+double DistributionWeighter::setParameterValues(ParameterPool *p_parameter_pool,
+		size_t index)
+{
+	if (index >= m_nbr_combinations) {
+		throw Exceptions::RuntimeErrorException(
+				"DistributionWeighter::setParameterValues: "
+				"index must be smaller than the total number of parameter "
+				"combinations");
+	}
+	size_t n_distr = m_distributions.size();
+	if (n_distr == 0) return 0.0;
+	double weight = 1.0;
+	for (size_t param_index=n_distr-1; ; --param_index) {
+		size_t remainder = index % m_distributions[param_index].getNbrSamples();
+		index /= m_distributions[param_index].getNbrSamples();
+		int changed = p_parameter_pool->setMatchedParametersValue(
+				m_distributions[param_index].getParameterName(),
+				m_cached_samples[param_index][remainder].value);
+		if (changed != 1) {
+			throw Exceptions::RuntimeErrorException(
+					"DistributionWeighter::setParameterValues: "
+					" parameter name matches nothing or more than "
+					"one parameter");
+		}
+		weight *= m_cached_samples[param_index][remainder].weight;
+		if (param_index==0) break;
+	}
+	return weight;
+}
diff --git a/Core/Tools/inc/IParameterized.h b/Core/Tools/inc/IParameterized.h
index 87b5974de4602bb47c29eda166983c54d8c11471..81172e9182a55c7e7ba8f38cc6fbdd109d931722 100644
--- a/Core/Tools/inc/IParameterized.h
+++ b/Core/Tools/inc/IParameterized.h
@@ -39,10 +39,12 @@ public:
     //! Returns pointer to the parameter pool.
     const ParameterPool* getParameterPool() const { return& m_parameters; }
 
-    //! Creates new parameter pool, with all local parameter and parameters of children
+    //! Creates new parameter pool, with all local parameters
+    //! and parameters of children
     virtual ParameterPool* createParameterTree() const;
 
-    //! Adds parameters from local pool to external pool and call recursion over direct children.
+    //! Adds parameters from local pool to external pool and
+    //! call recursion over direct children.
     virtual std::string addParametersToExternalPool(
         std::string path,
         ParameterPool* external_pool,
diff --git a/Core/Tools/inc/ParameterDistribution.h b/Core/Tools/inc/ParameterDistribution.h
index 3130ba3d1642dc05e11a8978644ba70259fbccfe..3ed787ed6a6ac85d0a923aea64d5721ce52b061c 100644
--- a/Core/Tools/inc/ParameterDistribution.h
+++ b/Core/Tools/inc/ParameterDistribution.h
@@ -28,14 +28,23 @@ class IDistribution1D;
 class ParameterDistribution : public IParameterized
 {
 public:
-	ParameterDistribution(const std::string& name);
+	ParameterDistribution(const std::string &name);
+	ParameterDistribution(const ParameterDistribution &other);
 	~ParameterDistribution();
 
+	//! Overload assignment operator
+	ParameterDistribution& operator=(const ParameterDistribution &other);
+
 	//! set the distribution type, number of samples and
 	//! the range of sample values
 	void setDistribution(const IDistribution1D &distribution,
 			size_t nbr_samples, double sigma_factor=0.0);
 
+	//! get the parameter's name
+	std::string getParameterName() const {
+		return m_name;
+	}
+
 	//! get number of samples for this distribution
 	size_t getNbrSamples() const {
 		return m_nbr_samples;
diff --git a/Core/Tools/src/ParameterDistribution.cpp b/Core/Tools/src/ParameterDistribution.cpp
index 74a0e64a045787b292e81dc452020ec6264eadb5..38a74cddbdc77b7fdb0a2f30785715aa68e6cedb 100644
--- a/Core/Tools/src/ParameterDistribution.cpp
+++ b/Core/Tools/src/ParameterDistribution.cpp
@@ -27,10 +27,31 @@ ParameterDistribution::ParameterDistribution(const std::string& name)
 	init_parameters();
 }
 
+ParameterDistribution::ParameterDistribution(
+		const ParameterDistribution& other)
+: m_name(other.m_name)
+, m_nbr_samples(other.m_nbr_samples)
+, m_sigma_factor(other.m_sigma_factor)
+{
+	mP_distribution.reset(other.mP_distribution->clone());
+}
+
 ParameterDistribution::~ParameterDistribution()
 {
 }
 
+ParameterDistribution& ParameterDistribution::operator=(
+		const ParameterDistribution& other)
+{
+	if (this != &other) {
+		m_name = other.m_name;
+		m_nbr_samples = other.m_nbr_samples;
+		m_sigma_factor = other.m_sigma_factor;
+		mP_distribution.reset(other.mP_distribution->clone());
+	}
+	return *this;
+}
+
 void ParameterDistribution::setDistribution(const IDistribution1D& distribution,
 		size_t nbr_samples, double sigma_factor)
 {
diff --git a/Tests/UnitTests/TestCore/BeamTest.h b/Tests/UnitTests/TestCore/BeamTest.h
index 04bd0d8467dd48eff855d94d68815b9b9918f942..15b5423b7c20ed946b452052d261377c5eecf84f 100644
--- a/Tests/UnitTests/TestCore/BeamTest.h
+++ b/Tests/UnitTests/TestCore/BeamTest.h
@@ -30,12 +30,16 @@ BeamTest::~BeamTest()
 
 TEST_F(BeamTest, BeamInitialState)
 {
-    EXPECT_EQ(complex_t(0.0,0.0), emptyBeam.getCentralK()[0]);
+    EXPECT_DOUBLE_EQ(2.0*M_PI, emptyBeam.getCentralK()[0].real());
+    EXPECT_DOUBLE_EQ(0.0, emptyBeam.getCentralK()[0].imag());
     EXPECT_EQ(complex_t(0.0,0.0), emptyBeam.getCentralK()[1]);
     EXPECT_EQ(complex_t(0.0,0.0), emptyBeam.getCentralK()[2]);
     EXPECT_EQ(double(1.0), emptyBeam.getIntensity());
-    EXPECT_EQ(size_t(1), emptyBeam.getParameterPool()->size());
+    EXPECT_EQ(size_t(4), emptyBeam.getParameterPool()->size());
     EXPECT_EQ(double(1.0), emptyBeam.getParameterPool()->getParameter("intensity").getValue() );
+    EXPECT_EQ(double(1.0), emptyBeam.getParameterPool()->getParameter("wavelength").getValue() );
+    EXPECT_EQ(double(0.0), emptyBeam.getParameterPool()->getParameter("alpha").getValue() );
+    EXPECT_EQ(double(0.0), emptyBeam.getParameterPool()->getParameter("phi").getValue() );
     EXPECT_EQ(complex_t(0.5,0.0), emptyBeam.getPolarization()(0,0));
     EXPECT_EQ(complex_t(0.5,0.0), emptyBeam.getPolarization()(1,1));
     EXPECT_TRUE(emptyBeam.checkPolarization(emptyBeam.getPolarization()));
@@ -61,7 +65,7 @@ TEST_F(BeamTest, BeamAssignment)
     EXPECT_NEAR(2.85664, assignedBeam.getCentralK()[1].real(), 0.00001);
     EXPECT_NEAR(-5.28712, assignedBeam.getCentralK()[2].real(), 0.00001);
     EXPECT_EQ(double(2.0), assignedBeam.getIntensity());
-    EXPECT_EQ(size_t(1), assignedBeam.getParameterPool()->size());
+    EXPECT_EQ(size_t(4), assignedBeam.getParameterPool()->size());
     EXPECT_EQ(double(2.0), assignedBeam.getParameterPool()->getParameter("intensity").getValue() );
     EXPECT_EQ(complex_t(0.6,0.0), assignedBeam.getPolarization()(0,0));
     EXPECT_EQ(complex_t(0.4,0.0), assignedBeam.getPolarization()(1,1));