BornAgain  1.18.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 scattering at grazing incidence
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 #include "Base/Types/Exceptions.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  Layer* layer = m_layers[i]->clone();
45  if (i > 0 && interface->getRoughness())
46  ret->addLayerWithTopRoughness(*layer, *interface->getRoughness());
47  else
48  ret->addLayer(*layer);
49  }
50  return ret;
51 }
52 
53 //! Adds layer with default (zero) roughness
54 void MultiLayer::addLayer(const Layer& layer)
55 {
56  LayerRoughness zero_roughness;
57  addLayerWithTopRoughness(layer, zero_roughness);
58 }
59 
60 //! Adds layer with top roughness
62 {
63  Layer* new_layer = layer.clone();
64  if (numberOfLayers()) {
65  // not the top layer
66  const Layer* last_layer = m_layers.back();
67  LayerInterface* interface(nullptr);
68  if (roughness.getSigma() != 0.0)
69  interface = LayerInterface::createRoughInterface(last_layer, new_layer, roughness);
70  else
71  interface = LayerInterface::createSmoothInterface(last_layer, new_layer);
72  addAndRegisterInterface(interface);
73  } else {
74  // the top layer
75  if (new_layer->thickness() != 0.0)
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  if (roughness.getSigma() != 0.0)
81  throw std::runtime_error(
82  "Invalid call to MultiLayer::addLayer(): the semi-infinite top layer "
83  "cannot have roughness.");
84  }
85  addAndRegisterLayer(new_layer);
86 }
87 
88 const Layer* MultiLayer::layer(size_t i_layer) const
89 {
90  return m_layers[check_layer_index(i_layer)];
91 }
92 
93 const LayerInterface* MultiLayer::layerInterface(size_t i_interface) const
94 {
95  return m_interfaces[check_interface_index(i_interface)];
96 }
97 
99 {
100  if (crossCorrLength < 0.0)
101  throw Exceptions::LogicErrorException("Attempt to set crossCorrLength to negative value");
103 }
104 
106 {
107  m_ext_field = ext_field;
108 }
109 
111 {
113 }
114 
115 std::vector<const INode*> MultiLayer::getChildren() const
116 {
117  std::vector<const INode*> ret;
118  const size_t N = m_layers.size();
119  ret.reserve(N + m_interfaces.size());
120 
121  for (size_t i = 0; i < N; ++i) {
122  ret.push_back(m_layers[i]);
123  const LayerInterface* interface = MultiLayerUtils::LayerBottomInterface(*this, i);
124  if (interface)
125  ret.push_back(interface);
126  }
127  return ret;
128 }
129 
131 {
132  m_layers.push_back(child);
134  registerChild(child);
135 }
136 
138 {
139  m_interfaces.push_back(child);
140  registerChild(child);
141 }
142 
144 {
145  size_t n_layers = numberOfLayers();
146  for (size_t i = 0; i < numberOfLayers(); ++i)
147  m_layers[i]->registerThickness(i > 0 && i < n_layers - 1);
148 }
149 
150 size_t MultiLayer::check_layer_index(size_t i_layer) const
151 {
152  if (i_layer >= m_layers.size())
153  throw Exceptions::OutOfBoundsException("Layer index is out of bounds");
154  return i_layer;
155 }
156 
157 size_t MultiLayer::check_interface_index(size_t i_interface) const
158 {
159  if (i_interface >= m_interfaces.size())
160  throw Exceptions::OutOfBoundsException("Interface index is out of bounds");
161  return i_interface;
162 }
Defines many exception classes in namespace Exceptionss.
Defines and implements interface class ILayout.
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 RealParameter.
void registerChild(INode *node)
Definition: INode.cpp:58
RealParameter & registerParameter(const std::string &name, double *parpointer)
void setName(const std::string &name)
void registerVector(const std::string &base_name, kvector_t *p_vec, const std::string &units="nm")
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, with thickness (in nanometer) and material.
Definition: Layer.h:28
double thickness() const
Definition: Layer.h:39
Layer * clone() const override final
Returns a clone of this ISample object.
Definition: Layer.cpp:33
Our sample model: a stack of layers one below the other.
Definition: MultiLayer.h:42
size_t check_layer_index(size_t i_layer) const
Checks index of layer w.r.t. vector length.
Definition: MultiLayer.cpp:150
SafePointerVector< LayerInterface > m_interfaces
stack of layer interfaces [nlayers-1]
Definition: MultiLayer.h:104
double m_crossCorrLength
cross correlation length (in z direction) between different layers
Definition: MultiLayer.h:106
void setRoughnessModel(RoughnessModel roughnessModel)
Definition: MultiLayer.cpp:110
const LayerInterface * layerInterface(size_t i_interface) const
Returns interface with given index.
Definition: MultiLayer.cpp:93
const Layer * layer(size_t i_layer) const
Returns layer with given index.
Definition: MultiLayer.cpp:88
MultiLayer * clone() const final override
Returns a clone of multilayer with clones of all layers and interfaces between layers.
Definition: MultiLayer.cpp:36
kvector_t externalField() const
Returns the external field applied to the multilayer (units: A/m)
Definition: MultiLayer.h:77
void addAndRegisterLayer(Layer *child)
Adds the layer with simultaneous registration in parent class.
Definition: MultiLayer.cpp:130
std::vector< const INode * > getChildren() const final override
Returns a vector of children (const).
Definition: MultiLayer.cpp:115
SafePointerVector< Layer > m_layers
stack of layers [nlayers]
Definition: MultiLayer.h:102
void handleLayerThicknessRegistration()
Handles correct registration of layer thicknesses (not needed for top and bottom layer)
Definition: MultiLayer.cpp:143
size_t check_interface_index(size_t i_interface) const
Checks index of interface w.r.t. vector length.
Definition: MultiLayer.cpp:157
void setExternalField(kvector_t ext_field)
Sets the external field applied to the multilayer (units: A/m)
Definition: MultiLayer.cpp:105
kvector_t m_ext_field
external magnetic field (in A/m)
Definition: MultiLayer.h:108
RoughnessModel roughnessModel() const
Definition: MultiLayer.h:83
void setCrossCorrLength(double crossCorrLength)
Sets cross correlation length of roughnesses between interfaces.
Definition: MultiLayer.cpp:98
RoughnessModel m_roughness_model
Definition: MultiLayer.h:110
size_t numberOfLayers() const
Definition: MultiLayer.h:53
~MultiLayer() override
void addLayer(const Layer &layer)
Adds object to multilayer.
Definition: MultiLayer.cpp:54
void addLayerWithTopRoughness(const Layer &layer, const LayerRoughness &roughness)
Adds layer with top roughness.
Definition: MultiLayer.cpp:61
double crossCorrLength() const
Returns cross correlation length of roughnesses between interfaces.
Definition: MultiLayer.h:71
void addAndRegisterInterface(LayerInterface *child)
Adds the interface with simultaneous registration in parent class.
Definition: MultiLayer.cpp:137
RealParameter & setNonnegative()
RealParameter & setUnit(const std::string &name)
size_t size() const
void push_back(T *pointer)
const LayerInterface * LayerBottomInterface(const MultiLayer &multilayer, size_t i)
Returns bottom interface of layer.