BornAgain  1.18.0
Simulate and fit neutron and x-ray scattering at grazing incidence
ProcessedSample Class Reference
Collaboration diagram for ProcessedSample:

Public Member Functions

 ProcessedSample (const MultiLayer &sample, const SimulationOptions &options)
 
 ~ProcessedSample ()
 
size_t numberOfSlices () const
 
const std::vector< Slice > & slices () const
 
const std::vector< Slice > & averageSlices () const
 
const std::vector< ProcessedLayout > & layouts () const
 
const IFresnelMapfresnelMap () const
 
double crossCorrelationLength () const
 
kvector_t externalField () const
 
const LayerRoughnessbottomRoughness (size_t i) const
 
double sliceTopZ (size_t i) const
 
double sliceBottomZ (size_t i) const
 
bool containsMagneticMaterial () const
 
bool hasRoughness () const
 
double crossCorrSpectralFun (const kvector_t kvec, size_t j, size_t k) const
 

Private Member Functions

void initSlices (const MultiLayer &sample, const SimulationOptions &options)
 
void initLayouts (const MultiLayer &sample)
 
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 initBFields ()
 
void mergeRegionMap (const std::map< size_t, std::vector< HomogeneousRegion >> &region_map)
 
void initFresnelMap (const SimulationOptions &sim_options)
 

Private Attributes

std::unique_ptr< IFresnelMapmP_fresnel_map
 
std::vector< Slicem_slices
 
double m_top_z
 
bool m_polarized
 
std::vector< ProcessedLayoutm_layouts
 
double m_crossCorrLength
 
kvector_t m_ext_field
 
std::map< size_t, std::vector< HomogeneousRegion > > m_region_map
 

Detailed Description

Data structure that contains all the necessary data for scattering calculations.

If the usage of average materials is requested, layers and particles are sliced into multiple slices and the average material is calculated for each slice.

Definition at line 37 of file ProcessedSample.h.

Constructor & Destructor Documentation

◆ ProcessedSample()

ProcessedSample::ProcessedSample ( const MultiLayer sample,
const SimulationOptions options 
)

Definition at line 40 of file ProcessedSample.cpp.

41  : m_slices{}, m_top_z{0.0}, m_polarized{false}, m_crossCorrLength{sample.crossCorrLength()},
42  m_ext_field{sample.externalField()}
43 {
44  initSlices(sample, options);
45  mP_fresnel_map = CreateFresnelMap(sample, m_slices, options);
46  initBFields();
47  initLayouts(sample);
48  initFresnelMap(options);
49 }
kvector_t externalField() const
Returns the external field applied to the multilayer (units: A/m)
Definition: MultiLayer.h:77
double crossCorrLength() const
Returns cross correlation length of roughnesses between interfaces.
Definition: MultiLayer.h:71
void initLayouts(const MultiLayer &sample)
std::vector< Slice > m_slices
void initSlices(const MultiLayer &sample, const SimulationOptions &options)
void initFresnelMap(const SimulationOptions &sim_options)
std::unique_ptr< IFresnelMap > mP_fresnel_map
double m_crossCorrLength
kvector_t m_ext_field
std::unique_ptr< IFresnelMap > CreateFresnelMap(const MultiLayer &sample, const std::vector< Slice > &slices, const SimulationOptions &options)

References anonymous_namespace{ProcessedSample.cpp}::CreateFresnelMap(), initBFields(), initFresnelMap(), initLayouts(), initSlices(), m_slices, and mP_fresnel_map.

Here is the call graph for this function:

◆ ~ProcessedSample()

ProcessedSample::~ProcessedSample ( )
default

Member Function Documentation

◆ numberOfSlices()

size_t ProcessedSample::numberOfSlices ( ) const

Definition at line 53 of file ProcessedSample.cpp.

54 {
55  return m_slices.size();
56 }

References m_slices.

Referenced by DepthProbeComputationTerm::compute(), RoughMultiLayerComputation::compute(), ProfileHelper::ProfileHelper(), and sliceBottomZ().

◆ slices()

const std::vector< Slice > & ProcessedSample::slices ( ) const

Definition at line 58 of file ProcessedSample.cpp.

59 {
60  return m_slices;
61 }

References m_slices.

Referenced by RoughMultiLayerComputation::get_refractive_term(), and RoughMultiLayerComputation::get_sum8terms().

◆ averageSlices()

const std::vector< Slice > & ProcessedSample::averageSlices ( ) const

Definition at line 63 of file ProcessedSample.cpp.

64 {
65  return mP_fresnel_map->slices();
66 }

References mP_fresnel_map.

Referenced by ProfileHelper::ProfileHelper().

◆ layouts()

const std::vector< ProcessedLayout > & ProcessedSample::layouts ( ) const

Definition at line 68 of file ProcessedSample.cpp.

69 {
70  return m_layouts;
71 }
std::vector< ProcessedLayout > m_layouts

References m_layouts.

◆ fresnelMap()

const IFresnelMap * ProcessedSample::fresnelMap ( ) const

Definition at line 73 of file ProcessedSample.cpp.

74 {
75  return mP_fresnel_map.get();
76 }

References mP_fresnel_map.

Referenced by DepthProbeComputationTerm::compute(), and RoughMultiLayerComputation::get_sum8terms().

◆ crossCorrelationLength()

double ProcessedSample::crossCorrelationLength ( ) const

Definition at line 78 of file ProcessedSample.cpp.

79 {
80  return m_crossCorrLength;
81 }

References m_crossCorrLength.

Referenced by RoughMultiLayerComputation::compute().

◆ externalField()

kvector_t ProcessedSample::externalField ( ) const

Definition at line 83 of file ProcessedSample.cpp.

84 {
85  return m_ext_field;
86 }

References m_ext_field.

◆ bottomRoughness()

const LayerRoughness * ProcessedSample::bottomRoughness ( size_t  i) const

Definition at line 88 of file ProcessedSample.cpp.

89 {
90  if (i + 2 > m_slices.size())
91  throw std::runtime_error("ProcessedSample::bottomRoughness: "
92  "index out of bounds.");
93  return m_slices[i + 1].topRoughness();
94 }

References m_slices.

Referenced by RoughMultiLayerComputation::compute(), crossCorrSpectralFun(), RoughMultiLayerComputation::get_sum8terms(), and ProfileHelper::ProfileHelper().

◆ sliceTopZ()

double ProcessedSample::sliceTopZ ( size_t  i) const

Definition at line 96 of file ProcessedSample.cpp.

97 {
98  if (i == 0)
99  return m_top_z;
100  return sliceBottomZ(i - 1);
101 }
double sliceBottomZ(size_t i) const

References m_top_z, and sliceBottomZ().

Referenced by DepthProbeComputationTerm::compute().

Here is the call graph for this function:

◆ sliceBottomZ()

double ProcessedSample::sliceBottomZ ( size_t  i) const

Definition at line 103 of file ProcessedSample.cpp.

104 {
105  if (numberOfSlices() < 2)
106  return m_top_z;
107  // Last slice has no bottom:
108  if (i + 2 > numberOfSlices())
109  i = numberOfSlices() - 2;
110  auto z = m_top_z;
111  for (size_t j = 1; j <= i; ++j)
112  z -= m_slices[j].thickness();
113  return z;
114 }
size_t numberOfSlices() const

References m_slices, m_top_z, and numberOfSlices().

Referenced by DepthProbeComputationTerm::compute(), crossCorrSpectralFun(), ProfileHelper::ProfileHelper(), and sliceTopZ().

Here is the call graph for this function:

◆ containsMagneticMaterial()

bool ProcessedSample::containsMagneticMaterial ( ) const

Definition at line 116 of file ProcessedSample.cpp.

117 {
118  return m_polarized;
119 }

References m_polarized.

◆ hasRoughness()

bool ProcessedSample::hasRoughness ( ) const

Definition at line 121 of file ProcessedSample.cpp.

122 {
123  for (auto& slice : m_slices) {
124  if (slice.topRoughness())
125  return true;
126  }
127  return false;
128 }

References m_slices.

◆ crossCorrSpectralFun()

double ProcessedSample::crossCorrSpectralFun ( const kvector_t  kvec,
size_t  j,
size_t  k 
) const

Fourier transform of the correlation function of roughnesses between the interfaces.

Definition at line 130 of file ProcessedSample.cpp.

131 {
132  if (m_crossCorrLength <= 0.0)
133  return 0.0;
134  double z_j = sliceBottomZ(j);
135  double z_k = sliceBottomZ(k);
136  const LayerRoughness* rough_j = bottomRoughness(j);
137  const LayerRoughness* rough_k = bottomRoughness(k);
138  if (!rough_j || !rough_k)
139  return 0.0;
140  double sigma_j = rough_j->getSigma();
141  double sigma_k = rough_k->getSigma();
142  if (sigma_j <= 0 || sigma_k <= 0)
143  return 0.0;
144  double corr = 0.5
145  * ((sigma_k / sigma_j) * rough_j->getSpectralFun(kvec)
146  + (sigma_j / sigma_k) * rough_k->getSpectralFun(kvec))
147  * std::exp(-1 * std::abs(z_j - z_k) / m_crossCorrLength);
148  return corr;
149 }
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.
const LayerRoughness * bottomRoughness(size_t i) const

References bottomRoughness(), LayerRoughness::getSigma(), LayerRoughness::getSpectralFun(), m_crossCorrLength, and sliceBottomZ().

Referenced by RoughMultiLayerComputation::compute().

Here is the call graph for this function:

◆ initSlices()

void ProcessedSample::initSlices ( const MultiLayer sample,
const SimulationOptions options 
)
private

Definition at line 152 of file ProcessedSample.cpp.

153 {
154  if (sample.numberOfLayers() == 0)
155  return;
156  bool use_slicing = options.useAvgMaterials() && sample.numberOfLayers() > 1;
157  auto layer_limits = MultiLayerUtils::ParticleRegions(sample, use_slicing);
158  for (size_t i = 0; i < sample.numberOfLayers(); ++i) {
159  auto p_layer = sample.layer(i);
160  auto n_slices = p_layer->numberOfSlices();
161  const ZLimits& slice_limits = layer_limits[i];
162  double tl = p_layer->thickness();
163  const Material* p_material = p_layer->material();
164  auto p_roughness = MultiLayerUtils::LayerTopRoughness(sample, i);
165  if (p_roughness && p_roughness->getSigma() <= 0)
166  p_roughness = nullptr;
167  // if no slicing is needed, create single slice for the layer
168  if (!slice_limits.isFinite() || n_slices == 0) {
169  if (i == sample.numberOfLayers() - 1)
170  tl = 0.0;
171  addSlice(tl, *p_material, p_roughness);
172  continue;
173  }
174  double top = slice_limits.upperLimit().m_value;
175  double bottom = slice_limits.lowerLimit().m_value;
176  // top layer
177  if (i == 0) {
178  if (top <= 0)
179  throw std::runtime_error("ProcessedSample::ProcessedSample: "
180  "top limit for top layer must be > 0.");
181  addSlice(0.0, *p_material);
182  addNSlices(n_slices, top - bottom, *p_material);
183  if (bottom > 0) {
184  addSlice(bottom, *p_material);
185  }
186  m_top_z = top;
187  }
188  // middle or bottom layer
189  else {
190  if (top < 0) {
191  addSlice(-top, *p_material, p_roughness);
192  addNSlices(n_slices, top - bottom, *p_material);
193  } else {
194  addNSlices(n_slices, top - bottom, *p_material, p_roughness);
195  }
196  // middle layer
197  if (i < sample.numberOfLayers() - 1 && bottom > -tl) {
198  addSlice(bottom + tl, *p_material);
199  }
200  // bottom layer
201  if (i == sample.numberOfLayers() - 1) {
202  addSlice(0.0, *p_material);
203  }
204  }
205  }
206 }
A wrapper for underlying material implementation.
Definition: Material.h:29
const Layer * layer(size_t i_layer) const
Returns layer with given index.
Definition: MultiLayer.cpp:88
size_t numberOfLayers() const
Definition: MultiLayer.h:53
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)
bool useAvgMaterials() const
Class that contains upper and lower limits of the z-coordinate for the slicing of form factors.
Definition: ZLimits.h:41
OneSidedLimit lowerLimit() const
Definition: ZLimits.cpp:39
OneSidedLimit upperLimit() const
Definition: ZLimits.cpp:44
bool isFinite() const
Definition: ZLimits.cpp:32
const LayerRoughness * LayerTopRoughness(const MultiLayer &multilayer, size_t i)
Returns top roughness of layer.
std::vector< ZLimits > ParticleRegions(const MultiLayer &multilayer, bool use_slicing)
Calculate z-regions occupied by particles.
double m_value
Definition: ZLimits.h:32

References addNSlices(), addSlice(), ZLimits::isFinite(), MultiLayer::layer(), MultiLayerUtils::LayerTopRoughness(), ZLimits::lowerLimit(), m_top_z, OneSidedLimit::m_value, anonymous_namespace{SlicedCylindersBuilder.cpp}::n_slices(), MultiLayer::numberOfLayers(), MultiLayerUtils::ParticleRegions(), ZLimits::upperLimit(), and SimulationOptions::useAvgMaterials().

Referenced by ProcessedSample().

Here is the call graph for this function:

◆ initLayouts()

void ProcessedSample::initLayouts ( const MultiLayer sample)
private

Definition at line 208 of file ProcessedSample.cpp.

209 {
210  double z_ref = -m_top_z;
212  for (size_t i = 0; i < sample.numberOfLayers(); ++i) {
213  if (i > 1)
214  z_ref -= MultiLayerUtils::LayerThickness(sample, i - 1);
215  auto p_layer = sample.layer(i);
216  for (auto p_layout : p_layer->layouts()) {
217  m_layouts.emplace_back(*p_layout, m_slices, z_ref, mP_fresnel_map.get(), m_polarized);
218  mergeRegionMap(m_layouts.back().regionMap());
219  }
220  }
221 }
void mergeRegionMap(const std::map< size_t, std::vector< HomogeneousRegion >> &region_map)
double LayerThickness(const MultiLayer &multilayer, size_t i)
Returns thickness of layer.
bool ContainsMagneticMaterial(const MultiLayer &sample)

References anonymous_namespace{ProcessedSample.cpp}::ContainsMagneticMaterial(), MultiLayer::layer(), MultiLayerUtils::LayerThickness(), m_layouts, m_polarized, m_slices, m_top_z, mergeRegionMap(), mP_fresnel_map, and MultiLayer::numberOfLayers().

Referenced by ProcessedSample().

Here is the call graph for this function:

◆ addSlice()

void ProcessedSample::addSlice ( double  thickness,
const Material material,
const LayerRoughness p_roughness = nullptr 
)
private

Definition at line 223 of file ProcessedSample.cpp.

225 {
226  if (p_roughness) {
227  m_slices.emplace_back(thickness, material, *p_roughness);
228  } else {
229  m_slices.emplace_back(thickness, material);
230  }
231 }

References m_slices.

Referenced by addNSlices(), and initSlices().

◆ addNSlices()

void ProcessedSample::addNSlices ( size_t  n,
double  thickness,
const Material material,
const LayerRoughness p_roughness = nullptr 
)
private

Definition at line 233 of file ProcessedSample.cpp.

235 {
236  if (thickness <= 0.0)
237  return;
238  if (n == 0)
239  throw std::runtime_error("ProcessedSample::addNSlices: number of slices should be "
240  "bigger than zero.");
241  double slice_thickness = thickness / n;
242  addSlice(slice_thickness, material, p_roughness);
243  for (size_t i = 1; i < n; ++i) {
244  addSlice(slice_thickness, material);
245  }
246 }

References addSlice().

Referenced by initSlices().

Here is the call graph for this function:

◆ initBFields()

void ProcessedSample::initBFields ( )
private

Definition at line 248 of file ProcessedSample.cpp.

249 {
250  if (m_slices.empty())
251  return;
252  double m_z0 = m_slices[0].material().magnetization().z();
253  double b_z = Slice::Magnetic_Permeability * (m_ext_field.z() + m_z0);
254  for (size_t i = 0; i < m_slices.size(); ++i) {
255  m_slices[i].initBField(m_ext_field, b_z);
256  }
257 }
T z() const
Returns z-component in cartesian coordinate system.
Definition: BasicVector3D.h:68
static constexpr double Magnetic_Permeability
Definition: Slice.h:58

References m_ext_field, m_slices, Slice::Magnetic_Permeability, and BasicVector3D< T >::z().

Referenced by ProcessedSample().

Here is the call graph for this function:

◆ mergeRegionMap()

void ProcessedSample::mergeRegionMap ( const std::map< size_t, std::vector< HomogeneousRegion >> &  region_map)
private

Definition at line 259 of file ProcessedSample.cpp.

261 {
262  for (auto& entry : region_map) {
263  size_t i = entry.first;
264  auto& regions = entry.second;
265  m_region_map[i].insert(m_region_map[i].begin(), regions.begin(), regions.end());
266  }
267 }
std::map< size_t, std::vector< HomogeneousRegion > > m_region_map

References m_region_map.

Referenced by initLayouts().

◆ initFresnelMap()

void ProcessedSample::initFresnelMap ( const SimulationOptions sim_options)
private

Definition at line 269 of file ProcessedSample.cpp.

270 {
271  if (sim_options.useAvgMaterials()) {
273  } else {
274  mP_fresnel_map->setSlices(m_slices);
275  }
276 }
std::vector< Slice > CreateAverageMaterialSlices(const std::vector< Slice > &slices, const std::map< size_t, std::vector< HomogeneousRegion >> &region_map)

References anonymous_namespace{ProcessedSample.cpp}::CreateAverageMaterialSlices(), m_region_map, m_slices, mP_fresnel_map, and SimulationOptions::useAvgMaterials().

Referenced by ProcessedSample().

Here is the call graph for this function:

Member Data Documentation

◆ mP_fresnel_map

std::unique_ptr<IFresnelMap> ProcessedSample::mP_fresnel_map
private

◆ m_slices

std::vector<Slice> ProcessedSample::m_slices
private

◆ m_top_z

double ProcessedSample::m_top_z
private

Definition at line 72 of file ProcessedSample.h.

Referenced by initLayouts(), initSlices(), sliceBottomZ(), and sliceTopZ().

◆ m_polarized

bool ProcessedSample::m_polarized
private

Definition at line 73 of file ProcessedSample.h.

Referenced by containsMagneticMaterial(), and initLayouts().

◆ m_layouts

std::vector<ProcessedLayout> ProcessedSample::m_layouts
private

Definition at line 74 of file ProcessedSample.h.

Referenced by initLayouts(), and layouts().

◆ m_crossCorrLength

double ProcessedSample::m_crossCorrLength
private

Definition at line 75 of file ProcessedSample.h.

Referenced by crossCorrelationLength(), and crossCorrSpectralFun().

◆ m_ext_field

kvector_t ProcessedSample::m_ext_field
private

Definition at line 76 of file ProcessedSample.h.

Referenced by externalField(), and initBFields().

◆ m_region_map

std::map<size_t, std::vector<HomogeneousRegion> > ProcessedSample::m_region_map
private

Definition at line 77 of file ProcessedSample.h.

Referenced by initFresnelMap(), and mergeRegionMap().


The documentation for this class was generated from the following files: