1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
|
// ************************************************************************************************
//
// BornAgain: simulate and fit reflection and scattering
//
//! @file Sample/Multilayer/Layer.cpp
//! @brief Implements class Layer.
//!
//! @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 "Sample/Multilayer/Layer.h"
#include "Base/Util/Assert.h"
#include "Base/Util/StringUtil.h"
#include "Sample/Aggregate/ParticleLayout.h"
#include "Sample/Interface/Roughness.h"
namespace {
Roughness* zeroRoughness()
{
SelfAffineFractalModel autocorr(0, 0.7, 25);
ErfTransient transient;
return new Roughness(&autocorr, &transient);
}
} // namespace
//! Constructor of a layer with thickness and material
//! @param material: material the layer is made of
//! @param thickness: thickness of a layer in nanometers
//! @param roughness: roughness of a top layer surface
Layer::Layer(const Material& material, double thickness, const Roughness* roughness)
: m_material(material)
, m_thickness(thickness)
, m_roughness(roughness ? roughness->clone() : zeroRoughness())
{
// If the roughness is not defined by user, it is equivalent to the situation when roughness is
// defined, but has zero rms. To avoid constant nullptr checks in the code and to ease
// resampling it was accepted that "Layer" should always have non-null roughness descriptor.
ASSERT(m_roughness);
if (thickness < 0.)
throw std::runtime_error("Layer contructor called with negative thickness");
validateOrThrow();
}
Layer::Layer(const Material& material, const Roughness* roughness)
: Layer(material, 0, roughness)
{
}
Layer::~Layer() = default;
Layer* Layer::clone() const
{
auto* result = new Layer(m_material, m_thickness, m_roughness.get());
result->m_B_field = m_B_field;
result->m_n_slices = m_n_slices;
for (const auto* layout : layouts())
result->addLayout(*layout);
return result;
}
std::vector<const INode*> Layer::nodeChildren() const
{
std::vector<const INode*> result;
for (const auto* layout : m_layouts)
result.push_back(layout);
result.push_back(m_roughness.get());
return result;
}
void Layer::addLayout(const ParticleLayout& layout)
{
m_layouts.push_back(layout.clone());
}
std::vector<const ParticleLayout*> Layer::layouts() const
{
std::vector<const ParticleLayout*> result;
for (const auto* layout : m_layouts)
result.push_back(layout);
return result;
}
void Layer::checkMaterials(double wavelength) const
{
m_material.checkRefractiveIndex(wavelength);
}
std::vector<const Layer*> Layer::unwrapped() const
{
return {this};
}
std::string Layer::validate() const
{
std::vector<std::string> errs;
for (size_t i = 0; i < m_layouts.size(); ++i) {
std::string err = m_layouts[i]->validate();
if (!err.empty())
errs.push_back("{ layout " + std::to_string(i) + ": " + err + " }");
}
if (!errs.empty())
return "[ " + Base::String::join(errs, ", ") + " ]";
return "";
}
|