31 std::unique_ptr<IFresnelMap> createFresnelMap(
const MultiLayer& sample,
32 const std::vector<Slice>& slices,
35 std::unique_ptr<IFresnelMap> result;
36 const bool magnetic = std::any_of(slices.cbegin(), slices.cend(), [](
const Slice& slice) {
37 return slice.material().isMagneticMaterial();
44 result->disableCaching();
48 bool checkRegions(
const std::vector<HomogeneousRegion>& regions)
50 double total_fraction = 0.0;
51 for (
const auto& region : regions)
52 total_fraction += region.m_volume;
53 return (total_fraction >= 0 && total_fraction <= 1);
57 createAverageMaterialSlices(
const std::vector<Slice>& slices,
58 const std::map<
size_t, std::vector<HomogeneousRegion>>& region_map)
60 std::vector<Slice> result = slices;
61 const auto last_slice_index = slices.size() - 1;
62 for (
const auto& entry : region_map) {
63 const auto i_slice = entry.first;
64 if (i_slice == 0 || i_slice == last_slice_index)
66 const auto slice_mat = slices[i_slice].material();
67 if (!checkRegions(entry.second))
68 throw std::runtime_error(
"createAverageMaterialSlices: "
69 "total volumetric fraction of particles exceeds 1!");
71 result[i_slice].setMaterial(new_material);
76 std::vector<double> bottomLayerCoordinates(
const MultiLayer& multilayer)
81 std::vector<double> result(n_layers - 1);
83 for (
size_t i = 1; i < n_layers - 1; ++i)
89 std::vector<ZLimits> particleRegions(
const MultiLayer& multilayer,
bool use_slicing)
91 const std::vector<double> bottom_coords = bottomLayerCoordinates(multilayer);
95 auto layer = multilayer.
layer(i);
96 double offset = (i == 0) ? 0 : bottom_coords[i - 1];
97 for (
const auto* layout : layer->layouts())
98 for (
const auto* particle : layout->particles())
99 layer_fill_limits.update(particle->bottomTopZ(), offset);
102 return layer_fill_limits.layerZLimits();
115 , m_polarized{forcePolarized}
116 , m_crossCorrLength{sample.crossCorrLength()}
117 , m_ext_field{sample.externalField()}
166 throw std::runtime_error(
"ProcessedSample::bottomRoughness: "
167 "index out of bounds.");
168 return m_slices[i + 1].topRoughness();
186 for (
size_t j = 1; j <= i; ++j)
199 if (slice.topRoughness())
212 if (!rough_j || !rough_k)
214 const double sigma_j = rough_j->
getSigma();
215 const double sigma_k = rough_k->
getSigma();
216 if (sigma_j <= 0 || sigma_k <= 0)
230 const auto layer_limits = particleRegions(sample, use_slicing);
232 const auto layer = sample.
layer(i);
234 const ZLimits& slice_limits = layer_limits[i];
235 double tl = layer->thickness();
236 const Material* material = layer->material();
238 if (roughness && roughness->getSigma() <= 0)
241 if (!slice_limits.
isFinite() || n_slices == 0) {
252 throw std::runtime_error(
"ProcessedSample::ProcessedSample: "
253 "top limit for top layer must be > 0.");
255 addNSlices(n_slices, top - bottom, *material);
263 addSlice(-top, *material, roughness);
264 addNSlices(n_slices, top - bottom, *material);
266 addNSlices(n_slices, top - bottom, *material, roughness);
286 auto layer = sample.
layer(i);
287 for (
const auto* layout : layer->layouts()) {
298 m_slices.emplace_back(thickness, material, *roughness);
300 m_slices.emplace_back(thickness, material);
306 if (thickness <= 0.0)
309 throw std::runtime_error(
"ProcessedSample::addNSlices: number of slices should be "
310 "bigger than zero.");
311 const double slice_thickness = thickness / n;
312 addSlice(slice_thickness, material, roughness);
313 for (
size_t i = 1; i < n; ++i)
314 addSlice(slice_thickness, material);
321 const double m_z0 =
m_slices[0].material().magnetization().z();
323 for (
size_t i = 0; i <
m_slices.size(); ++i) {
329 const std::map<
size_t, std::vector<HomogeneousRegion>>& region_map)
331 for (
const auto& entry : region_map) {
332 size_t i = entry.first;
333 auto& regions = entry.second;
Defines struct HomogeneousRegion, and declares fct createAveragedMaterial.
Defines interface IParticle.
Defines class LayerFillLimits.
Defines class LayerRoughness.
Defines class MatrixFresnelMap.
Defines helper functions for MultiLayer objects.
Defines class ParticleLayout.
Defines class ProcessedLayout.
Defines class ProcessedSample.
Defines class ScalarFresnelMap.
Defines class SimulationOptions.
Defines class SpecularStrategyBuilder.
T z() const
Returns z-component in cartesian coordinate system.
Holds the necessary information to calculate the radiation wavefunction in every layer for different ...
bool isMagnetic() const
Returns true if there is any magnetic material in this ISampleNode.
Helper class for the graded layer approximation.
A roughness of interface between two layers.
double getSigma() const
Returns rms of roughness.
double getSpectralFun(const kvector_t kvec) const
Returns power spectral density of the surface roughness.
unsigned int numberOfSlices() const
A wrapper for underlying material implementation.
Our sample model: a stack of layers one below the other.
const Layer * layer(size_t i_layer) const
Returns layer with given index.
size_t numberOfLayers() const
void initLayouts(const MultiLayer &sample)
const std::vector< Slice > & slices() const
std::vector< Slice > m_slices
std::map< size_t, std::vector< HomogeneousRegion > > m_region_map
void initSlices(const MultiLayer &sample, const SimulationOptions &options)
bool hasRoughness() const
double sliceTopZ(size_t i) const
kvector_t externalField() const
ProcessedSample(const MultiLayer &sample, const SimulationOptions &options, bool forcePolarized=false)
void addSlice(double thickness, const Material &material, const LayerRoughness *p_roughness=nullptr)
void addNSlices(size_t n, double thickness, const Material &material, const LayerRoughness *p_roughness=nullptr)
void mergeRegionMap(const std::map< size_t, std::vector< HomogeneousRegion >> ®ion_map)
double sliceBottomZ(size_t i) const
void initFresnelMap(const SimulationOptions &sim_options)
bool containsMagneticMaterial() const
std::unique_ptr< IFresnelMap > m_fresnel_map
const IFresnelMap * fresnelMap() const
size_t numberOfSlices() const
double crossCorrSpectralFun(const kvector_t kvec, size_t j, size_t k) const
Fourier transform of the correlation function of roughnesses between the interfaces.
const std::vector< Slice > & averageSlices() const
const std::vector< ProcessedLayout > & layouts() const
double crossCorrelationLength() const
const LayerRoughness * bottomRoughness(size_t i) const
std::vector< ProcessedLayout > m_layouts
Collect the different options for simulation.
bool useAvgMaterials() const
Data structure containing the data of a single slice, for calculating the Fresnel coefficients.
static constexpr double Magnetic_Permeability
static std::unique_ptr< ISpecularStrategy > build(const MultiLayer &sample, const bool magnetic)
Class that contains upper and lower limits of the z-coordinate for the slicing of form factors.
OneSidedLimit lowerLimit() const
OneSidedLimit upperLimit() const
Material createAveragedMaterial(const Material &layer_mat, const std::vector< HomogeneousRegion > ®ions)
Creates averaged material.
const LayerRoughness * LayerTopRoughness(const MultiLayer &multilayer, size_t i)
Returns top roughness of layer.