BornAgain  1.19.79
Open-source research software to simulate and fit neutron and x-ray reflectometry and grazing-incidence small-angle scattering
MultiLayer.cpp
Go to the documentation of this file.
1 // ************************************************************************************************
2 //
3 // BornAgain: simulate and fit reflection and scattering
4 //
5 //! @file Sample/Multilayer/MultiLayer.cpp
6 //! @brief Implements class MultiLayer.
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 
16 
17 #include "Base/Util/Assert.h"
18 #include "Fit/Param/RealLimits.h"
25 #include <utility>
26 
27 MultiLayer::MultiLayer(std::string name)
28  : m_crossCorrLength(0)
29  , m_sample_name(std::move(name))
30 {
31  RealLimits::nonnegative().check("CrossCorrelationLength", m_crossCorrLength);
32 }
33 
34 MultiLayer::~MultiLayer() = default;
35 
37 {
38  auto* result = new MultiLayer;
39  result->setCrossCorrLength(crossCorrLength());
40  result->setExternalField(externalField());
41  result->setRoughnessModel(roughnessModel());
42  for (size_t i = 0; i < numberOfLayers(); ++i) {
43  const LayerInterface* interface = i > 0 ? m_interfaces[i - 1] : nullptr;
44  if (i > 0 && interface->roughness())
45  result->addLayerWithTopRoughness(std::as_const(*m_layers[i]), *interface->roughness());
46  else
47  result->addLayer(std::as_const(*m_layers[i]));
48  }
49  return result;
50 }
51 
52 //! Adds layer with default (zero) roughness
53 void MultiLayer::addLayer(const Layer& layer)
54 {
55  LayerRoughness zero_roughness;
56  addLayerWithTopRoughness(layer, zero_roughness);
57 }
58 
59 //! Adds layer with top roughness
61 {
62  Layer* new_layer = layer.clone();
63  if (numberOfLayers()) {
64  // not the top layer
65  const Layer* last_layer = m_layers.back();
66  LayerInterface* interface(nullptr);
67  if (roughness.sigma() != 0.0)
68  interface = LayerInterface::createRoughInterface(last_layer, new_layer, roughness);
69  else
70  interface = LayerInterface::createSmoothInterface(last_layer, new_layer);
71  addInterface(interface);
72  } else {
73  // the top layer
74  if (new_layer->thickness() != 0.0) {
75  delete new_layer;
76  throw std::runtime_error(
77  "Invalid call to MultiLayer::addLayer(): the semi-infinite top layer "
78  "must have a pro forma thickness of 0");
79  }
80 
81  if (roughness.sigma() != 0.0) {
82  delete new_layer;
83  throw std::runtime_error(
84  "Invalid call to MultiLayer::addLayer(): the semi-infinite top layer "
85  "cannot have roughness.");
86  }
87  }
88  addLayer(new_layer);
89 }
90 
91 const Layer* MultiLayer::layer(size_t i_layer) const
92 {
93  return m_layers.at(i_layer);
94 }
95 
96 const LayerInterface* MultiLayer::layerInterface(size_t i_interface) const
97 {
98  return m_interfaces.at(i_interface);
99 }
100 
102 {
103  if (crossCorrLength < 0.0)
104  throw std::runtime_error("Attempt to set crossCorrLength to negative value");
106 }
107 
109 {
110  m_ext_field = ext_field;
111 }
112 
114 {
116 }
117 
118 std::vector<const INode*> MultiLayer::nodeChildren() const
119 {
120  std::vector<const INode*> result;
121  const size_t N = m_layers.size();
122  result.reserve(N + m_interfaces.size());
123 
124  for (size_t i = 0; i < N; ++i) {
125  result.push_back(layer(i));
126  if (i == N - 1)
127  break;
128  result.push_back(layerInterface(i));
129  }
130  return result;
131 }
132 
134 {
135  m_layers.emplace_back(child);
136 }
137 
139 {
140  m_interfaces.emplace_back(child);
141 }
Defines the macro ASSERT.
Defines class LayerInterface.
Defines class LayerRoughness.
Defines class Layer.
Declares functions in namespace MaterialUtils.
Defines class MultiLayer.
Defines namespace SampleUtils::Multilayer.
Defines class ParticleLayout.
Defines class RealLimits.
Interface between two layers, possibly with roughness.
static LayerInterface * createRoughInterface(const Layer *top_layer, const Layer *bottom_layer, const LayerRoughness &roughness)
Creates rough interface between two layers.
const LayerRoughness * roughness() const
Returns roughness of the interface.
static LayerInterface * createSmoothInterface(const Layer *top_layer, const Layer *bottom_layer)
Creates smooth interface between two layers.
A roughness of interface between two layers.
double sigma() const
Returns rms of roughness.
A layer in a MultiLayer sample.
Definition: Layer.h:26
double thickness() const
Definition: Layer.h:41
Layer * clone() const override
Returns a clone of this ISampleNode object.
Definition: Layer.cpp:31
Our sample model: a stack of layers one below the other.
Definition: MultiLayer.h:43
MultiLayer(std::string name="Unnamed")
Definition: MultiLayer.cpp:27
double m_crossCorrLength
cross correlation length (in z direction) between different layers
Definition: MultiLayer.h:90
R3 m_ext_field
external magnetic field (in A/m)
Definition: MultiLayer.h:92
void setRoughnessModel(RoughnessModel roughnessModel)
Definition: MultiLayer.cpp:113
const LayerInterface * layerInterface(size_t i_interface) const
Returns interface with given index.
Definition: MultiLayer.cpp:96
const Layer * layer(size_t i_layer) const
Returns layer with given index.
Definition: MultiLayer.cpp:91
OwningVector< LayerInterface > m_interfaces
stack of layer interfaces [nlayers-1]
Definition: MultiLayer.h:88
MultiLayer * clone() const override
Returns a clone of this ISampleNode object.
Definition: MultiLayer.cpp:36
R3 externalField() const
Returns the external field applied to the sample (units: A/m)
Definition: MultiLayer.h:71
RoughnessModel roughnessModel() const
Definition: MultiLayer.h:67
void setCrossCorrLength(double crossCorrLength)
Sets cross correlation length of roughnesses between interfaces.
Definition: MultiLayer.cpp:101
RoughnessModel m_roughness_model
Definition: MultiLayer.h:95
size_t numberOfLayers() const
Definition: MultiLayer.h:51
~MultiLayer() override
void addLayer(const Layer &layer)
Adds layer with default (zero) roughness.
Definition: MultiLayer.cpp:53
void setExternalField(R3 ext_field)
Sets the external field applied to the sample (units: A/m)
Definition: MultiLayer.cpp:108
void addInterface(LayerInterface *child)
Adds the interface with simultaneous registration in parent class.
Definition: MultiLayer.cpp:138
void addLayerWithTopRoughness(const Layer &layer, const LayerRoughness &roughness)
Adds layer with top roughness.
Definition: MultiLayer.cpp:60
double crossCorrLength() const
Returns cross correlation length of roughnesses between interfaces.
Definition: MultiLayer.h:69
OwningVector< Layer > m_layers
stack of layers [nlayers]
Definition: MultiLayer.h:86
std::vector< const INode * > nodeChildren() const override
Returns all children.
Definition: MultiLayer.cpp:118
void emplace_back(T *e)
Definition: OwningVector.h:62
size_t size() const
Definition: OwningVector.h:70
const T * back() const
Definition: OwningVector.h:74
T *const & at(int i) const
Definition: OwningVector.h:73
void check(const std::string &name, double value) const
Throws if value is outside limits. Parameter 'name' is for exception message.
Definition: RealLimits.cpp:170
static RealLimits nonnegative()
Creates an object which can have only positive values with 0. included.
Definition: RealLimits.cpp:124
#define N
Definition: mixmax.h:31