-
Wuttke, Joachim authoredWuttke, Joachim authored
QzScan.cpp 5.18 KiB
// ************************************************************************************************
//
// BornAgain: simulate and fit reflection and scattering
//
//! @file Sim/Scan/QzScan.cpp
//! @brief Implements QzScan class.
//!
//! @homepage http://www.bornagainproject.org
//! @license GNU General Public License v3 or higher (see COPYING)
//! @copyright Forschungszentrum Jülich GmbH 2018
//! @authors Scientific Computing Group at MLZ (see CITATION, AUTHORS)
//
// ************************************************************************************************
#include "Sim/Scan/QzScan.h"
#include "Base/Axis/FixedBinAxis.h"
#include "Base/Axis/PointwiseAxis.h"
#include "Device/Coord/CoordSystem1D.h"
#include "Device/Pol/PolFilter.h"
#include "Param/Distrib/ParameterSample.h"
#include "Param/Distrib/RangedDistributions.h"
#include "Resample/Element/SpecularElement.h"
#include "Sim/Scan/ScanResolution.h"
#include <algorithm>
QzScan::QzScan(IAxis* qs_nm)
: m_qs(std::move(qs_nm))
, m_resolution(scanEmptyResolution())
{
std::vector<double> axis_values = m_qs->binCenters();
if (!std::is_sorted(axis_values.begin(), axis_values.end()))
throw std::runtime_error("Error in QzScan::checkInitialization: q-vector values shall "
"be sorted in ascending order.");
if (axis_values.front() < 0)
throw std::runtime_error("Error in QzScan::checkInitialization: q-vector values are out "
"of acceptable range.");
}
QzScan::QzScan(std::vector<double> qs_nm)
: QzScan(new PointwiseAxis("qs", std::move(qs_nm)))
{
}
QzScan::QzScan(const IAxis& qs_nm)
: QzScan(qs_nm.clone())
{
}
QzScan::QzScan(int nbins, double qz_min, double qz_max)
: QzScan(new FixedBinAxis("qs", nbins, qz_min, qz_max))
{
}
QzScan::~QzScan() = default;
QzScan* QzScan::clone() const
{
auto* result = new QzScan(*m_qs);
result->setQResolution(*m_resolution);
result->setOffset(m_offset);
// TODO merge with same code in AlphaScan
if (m_beamPolarization)
result->m_beamPolarization.reset(new R3(*m_beamPolarization));
if (m_polAnalyzer)
result->m_polAnalyzer.reset(new PolFilter(*m_polAnalyzer));
return result;
}
//! Generates simulation elements for specular simulations
std::vector<SpecularElement> QzScan::generateElements() const
{
const auto samples = m_resolution->generateResolutionSamples(m_qs->binCenters());
std::vector<double> qz;
qz.reserve(numberOfElements());
for (size_t i = 0, size_out = samples.size(); i < size_out; ++i)
for (size_t j = 0, size_in = samples[i].size(); j < size_in; ++j)
qz.push_back(samples[i][j].value);
std::vector<SpecularElement> result;
result.reserve(qz.size());
for (size_t i = 0, size = qz.size(); i < size; ++i)
result.emplace_back(
SpecularElement::FromQzScan(-(qz[i] + m_offset) / 2.0, polMatrices(), qz[i] >= 0));
return result;
}
std::vector<double> QzScan::footprint(size_t i, size_t n_elements) const
{
if (i + n_elements > numberOfElements())
throw std::runtime_error("Error in QzScan::footprint: given index exceeds the "
"number of simulation elements");
return std::vector<double>(n_elements, 1.0);
}
//! Returns the number of simulation elements
size_t QzScan::numberOfElements() const
{
return m_qs->size() * m_resolution->nSamples();
}
CoordSystem1D* QzScan::scanCoordSystem() const
{
return new WavenumberReflectometryCoords(coordinateAxis()->clone());
}
std::vector<double> QzScan::createIntensities(const std::vector<SpecularElement>& eles) const
{
const size_t axis_size = m_qs->size();
std::vector<double> result(axis_size, 0.0);
const auto samples = m_resolution->generateResolutionSamples(m_qs->binCenters());
size_t elem_pos = 0;
for (size_t i = 0; i < axis_size; ++i) {
double& current = result[i];
for (size_t j = 0, size = samples[i].size(); j < size; ++j) {
current += eles[elem_pos].intensity() * samples[i][j].weight;
++elem_pos;
}
}
return result;
}
void QzScan::setQResolution(const IScanResolution& resolution)
{
m_resolution.reset(resolution.clone());
}
void QzScan::setRelativeQResolution(const IRangedDistribution& distr, double rel_dev)
{
std::unique_ptr<IScanResolution> resolution(scanRelativeResolution(distr, rel_dev));
setQResolution(*resolution);
}
void QzScan::setRelativeQVectorResolution(const IRangedDistribution& distr,
const std::vector<double>& rel_dev)
{
std::unique_ptr<IScanResolution> resolution(scanRelativeVectorResolution(distr, rel_dev));
setQResolution(*resolution);
}
void QzScan::setAbsoluteQResolution(const IRangedDistribution& distr, double std_dev)
{
std::unique_ptr<IScanResolution> resolution(scanAbsoluteResolution(distr, std_dev));
setQResolution(*resolution);
}
void QzScan::setAbsoluteQVectorResolution(const IRangedDistribution& distr,
const std::vector<double>& std_dev)
{
std::unique_ptr<IScanResolution> resolution(scanAbsoluteVectorResolution(distr, std_dev));
setQResolution(*resolution);
}