BornAgain  1.19.0
Simulate and fit neutron and x-ray scattering at grazing incidence
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 
15 #include "Base/Utils/Assert.h"
26 
27 MultiLayer::MultiLayer() : m_crossCorrLength(0)
28 {
29  setName("MultiLayer");
30  registerParameter("CrossCorrelationLength", &m_crossCorrLength).setUnit("nm").setNonnegative();
31  registerVector("ExternalField", &m_ext_field, "");
32 }
33 
34 MultiLayer::~MultiLayer() = default;
35 
37 {
38  auto* ret = new MultiLayer;
39  ret->setCrossCorrLength(crossCorrLength());
40  ret->setExternalField(externalField());
41  ret->setRoughnessModel(roughnessModel());
42  for (size_t i = 0; i < numberOfLayers(); ++i) {
43  const auto* interface = i > 0 ? m_interfaces[i - 1] : nullptr;
44  if (i > 0 && interface->getRoughness())
45  ret->addLayerWithTopRoughness(std::as_const(*m_layers[i]), *interface->getRoughness());
46  else
47  ret->addLayer(std::as_const(*m_layers[i]));
48  }
49  return ret;
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.getSigma() != 0.0)
68  interface = LayerInterface::createRoughInterface(last_layer, new_layer, roughness);
69  else
70  interface = LayerInterface::createSmoothInterface(last_layer, new_layer);
71  addAndRegisterInterface(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.getSigma() != 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  addAndRegisterLayer(new_layer);
89 }
90 
91 const Layer* MultiLayer::layer(size_t i_layer) const
92 {
93  return m_layers[check_layer_index(i_layer)];
94 }
95 
96 const LayerInterface* MultiLayer::layerInterface(size_t i_interface) const
97 {
98  return m_interfaces[check_interface_index(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::getChildren() const
119 {
120  std::vector<const INode*> ret;
121  const size_t N = m_layers.size();
122  ret.reserve(N + m_interfaces.size());
123 
124  for (size_t i = 0; i < N; ++i) {
125  ret.push_back(m_layers[i]);
126  if (i == N - 1)
127  break;
128  ret.push_back(layerInterface(i));
129  }
130  return ret;
131 }
132 
134 {
135  m_layers.push_back(child);
137  registerChild(child);
138 }
139 
141 {
142  m_interfaces.push_back(child);
143  registerChild(child);
144 }
145 
147 {
148  size_t n_layers = numberOfLayers();
149  ASSERT(n_layers > 0);
150  m_layers[n_layers-1]->registerThickness(false);
151  if(n_layers > 2)
152  m_layers[n_layers-2]->registerThickness();
153 }
154 
155 size_t MultiLayer::check_layer_index(size_t i_layer) const
156 {
157  if (i_layer >= m_layers.size())
158  throw std::runtime_error("Layer index is out of bounds");
159  return i_layer;
160 }
161 
162 size_t MultiLayer::check_interface_index(size_t i_interface) const
163 {
164  if (i_interface >= m_interfaces.size())
165  throw std::runtime_error("Interface index is out of bounds");
166  return i_interface;
167 }
Defines the macro ASSERT.
#define ASSERT(condition)
Definition: Assert.h:31
Defines class LayerFillLimits.
Defines class LayerInterface.
Defines class LayerRoughness.
Defines class Layer.
Declares functions in namespace MaterialUtils.
Defines helper functions for MultiLayer objects.
Defines class MultiLayer.
Defines class ParameterPool.
Defines class ParticleLayout.
Defines class RealParameter.
void registerChild(INode *node)
Definition: INode.cpp:57
void registerVector(const std::string &base_name, kvector_t *p_vec, const std::string &units="nm")
void setName(const std::string &name)
RealParameter & registerParameter(const std::string &name, double *parpointer)
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.
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 getSigma() const
Returns rms of roughness.
A layer in a MultiLayer sample.
Definition: Layer.h:27
double thickness() const
Definition: Layer.h:38
Layer * clone() const final
Returns a clone of this ISampleNode object.
Definition: Layer.cpp:34
Our sample model: a stack of layers one below the other.
Definition: MultiLayer.h:41
size_t check_layer_index(size_t i_layer) const
Checks index of layer w.r.t. vector length.
Definition: MultiLayer.cpp:155
SafePointerVector< LayerInterface > m_interfaces
stack of layer interfaces [nlayers-1]
Definition: MultiLayer.h:93
double m_crossCorrLength
cross correlation length (in z direction) between different layers
Definition: MultiLayer.h:95
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
kvector_t externalField() const
Returns the external field applied to the multilayer (units: A/m)
Definition: MultiLayer.h:70
void addAndRegisterLayer(Layer *child)
Adds the layer with simultaneous registration in parent class.
Definition: MultiLayer.cpp:133
SafePointerVector< Layer > m_layers
stack of layers [nlayers]
Definition: MultiLayer.h:91
void handleLayerThicknessRegistration()
Handles correct registration of layer thicknesses (not needed for top and bottom layer)
Definition: MultiLayer.cpp:146
std::vector< const INode * > getChildren() const final
Returns a vector of children.
Definition: MultiLayer.cpp:118
size_t check_interface_index(size_t i_interface) const
Checks index of interface w.r.t. vector length.
Definition: MultiLayer.cpp:162
void setExternalField(kvector_t ext_field)
Sets the external field applied to the multilayer (units: A/m)
Definition: MultiLayer.cpp:108
kvector_t m_ext_field
external magnetic field (in A/m)
Definition: MultiLayer.h:97
RoughnessModel roughnessModel() const
Definition: MultiLayer.h:66
void setCrossCorrLength(double crossCorrLength)
Sets cross correlation length of roughnesses between interfaces.
Definition: MultiLayer.cpp:101
RoughnessModel m_roughness_model
Definition: MultiLayer.h:99
size_t numberOfLayers() const
Definition: MultiLayer.h:50
~MultiLayer() override
void addLayer(const Layer &layer)
Adds layer with default (zero) roughness.
Definition: MultiLayer.cpp:53
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:68
void addAndRegisterInterface(LayerInterface *child)
Adds the interface with simultaneous registration in parent class.
Definition: MultiLayer.cpp:140
MultiLayer * clone() const final
Returns a clone of this ISampleNode object.
Definition: MultiLayer.cpp:36
RealParameter & setNonnegative()
RealParameter & setUnit(const std::string &name)
size_t size() const
void push_back(T *pointer)