BornAgain  1.19.79
Open-source research software to simulate and fit neutron and x-ray reflectometry and grazing-incidence small-angle scattering
ProfileHelper.cpp
Go to the documentation of this file.
1 // ************************************************************************************************
2 //
3 // BornAgain: simulate and fit reflection and scattering
4 //
5 //! @file Resample/Slice/ProfileHelper.cpp
6 //! @brief Implements class ProfileHelper.
7 //!
8 //! @homepage http://www.bornagainproject.org
9 //! @license GNU General Public License v3 or higher (see COPYING)
10 //! @copyright Forschungszentrum Jülich GmbH 2018
11 //! @authors Scientific Computing Group at MLZ (see CITATION, AUTHORS)
12 //
13 // ************************************************************************************************
14 
18 
19 namespace {
20 
21 const double prefactor = std::sqrt(2.0 / M_PI);
22 
23 double TransitionTanh(double x)
24 {
25  return (1.0 - std::tanh(prefactor * x)) / 2.0;
26 }
27 
28 double Transition(double x, double sigma)
29 {
30  if (sigma <= 0.0)
31  return x < 0.0 ? 1.0 : 0.0;
32  return TransitionTanh(x / sigma);
33 }
34 
35 } // namespace
36 
37 
39  : m_stack(stack)
40 {
41 }
42 
43 // Note: for refractive index materials, the material interpolation actually happens at the level
44 // of n^2. To first order in delta and beta, this implies the same smooth interpolation of delta
45 // and beta, as is done here.
46 std::vector<complex_t> ProfileHelper::calculateProfile(const std::vector<double>& z_values) const
47 {
48  const complex_t top_value = !m_stack.empty() ? m_stack.at(0).material().materialData() : 0.0;
49  std::vector<complex_t> result(z_values.size(), top_value);
50  for (size_t i = 1; i < m_stack.size(); ++i) {
51  const Slice& slice = m_stack.at(i);
52  const Slice& sliceAbove = m_stack.at(i - 1);
53  const complex_t sld_diff =
54  slice.material().materialData() - sliceAbove.material().materialData();
55  for (size_t j = 0; j < z_values.size(); ++j) {
56  const double arg = (z_values[j] - slice.zTop());
57  const LayerRoughness* roughness = slice.topRoughness();
58  const double t = Transition(arg, roughness ? roughness->sigma() : 0);
59  result[j] += sld_diff * t;
60  }
61  }
62  return result;
63 }
64 
65 std::pair<double, double> ProfileHelper::defaultLimits() const
66 {
67  if (m_stack.size() < 2)
68  return {0.0, 0.0};
69  double interface_span = m_stack.front().zBottom() - m_stack.back().zTop();
70  double default_margin = interface_span > 0.0 ? interface_span / 20.0 : 10.0;
71  const LayerRoughness* topRoughness = m_stack.at(1).topRoughness();
72  const LayerRoughness* bottomRoughness = m_stack.back().topRoughness();
73 
74  double top_margin =
75  topRoughness && topRoughness->sigma() > 0 ? 5.0 * topRoughness->sigma() : default_margin;
76  double bottom_margin = bottomRoughness && bottomRoughness->sigma() > 0
77  ? 5.0 * bottomRoughness->sigma()
78  : default_margin;
79  double z_min = m_stack.back().zTop() - bottom_margin;
80  double z_max = m_stack.front().zBottom() + top_margin;
81  return {z_min, z_max};
82 }
#define M_PI
Definition: Constants.h:44
Defines class LayerRoughness.
Defines class ProfileHelper.
Defines class SliceStack.
A roughness of interface between two layers.
double sigma() const
Returns rms of roughness.
complex_t materialData() const
Returns delta + i beta.
Definition: Material.cpp:83
std::pair< double, double > defaultLimits() const
std::vector< complex_t > calculateProfile(const std::vector< double > &z_values) const
const SliceStack & m_stack
Definition: ProfileHelper.h:43
ProfileHelper(const SliceStack &stack)
A stack of Slices.
Definition: SliceStack.h:38
Data structure containing the data of a single slice, for calculating the Fresnel coefficients.
Definition: Slice.h:31
double zTop() const
Definition: Slice.cpp:61
const Material & material() const
Definition: Slice.cpp:51
const LayerRoughness * topRoughness() const
Definition: Slice.cpp:76