BornAgain  1.18.0
Simulate and fit neutron and x-ray scattering at grazing incidence
HomogeneousRegion.cpp
Go to the documentation of this file.
1 // ************************************************************************** //
2 //
3 // BornAgain: simulate and fit scattering at grazing incidence
4 //
5 //! @file Sample/Particle/HomogeneousRegion.cpp
6 //! @brief Implements fct createAveragedMaterial
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/Const/Units.h"
20 #include <functional>
21 
22 namespace
23 {
24 
25 template <class T>
26 T averageData(const Material& layer_mat, const std::vector<HomogeneousRegion>& regions,
27  std::function<T(const Material&)> average)
28 {
29  const T layer_data = average(layer_mat);
30  T averaged_data = layer_data;
31  for (auto& region : regions)
32  averaged_data += region.m_volume * (average(region.m_material) - layer_data);
33  return averaged_data;
34 }
35 
36 } // namespace
37 
39  const std::vector<HomogeneousRegion>& regions)
40 {
41  // determine the type of returned material
42  std::vector<const Material*> materials(regions.size() + 1);
43  materials[0] = &layer_mat;
44  for (size_t i = 0, regions_size = regions.size(); i < regions_size; ++i)
45  materials[i + 1] = &regions[i].m_material;
46  const MATERIAL_TYPES avr_material_type = MaterialUtils::checkMaterialTypes(materials);
47  if (avr_material_type == MATERIAL_TYPES::InvalidMaterialType)
48  throw std::runtime_error("Error in createAveragedMaterial(): non-default materials of "
49  "different types used simultaneously.");
50 
51  // create the name of returned material
52  const std::string avr_mat_name = layer_mat.getName() + "_avg";
53 
54  // calculate averaged magnetization
55  const kvector_t mag_avr = averageData<kvector_t>(
56  layer_mat, regions, [](const Material& mat) { return mat.magnetization(); });
57 
58  if (avr_material_type == MATERIAL_TYPES::RefractiveMaterial) {
59  // avrData returns (1 - mdc)^2 - 1, where mdc is material data conjugate
60  auto avrData = [](const Material& mat) -> complex_t {
61  const complex_t mdc = std::conj(mat.materialData());
62  return mdc * mdc - 2.0 * mdc;
63  };
64  const complex_t avr_mat_data =
65  std::conj(1.0 - std::sqrt(1.0 + averageData<complex_t>(layer_mat, regions, avrData)));
66  return HomogeneousMaterial(avr_mat_name, avr_mat_data.real(), avr_mat_data.imag(), mag_avr);
67  } else if (avr_material_type == MATERIAL_TYPES::MaterialBySLD) {
68  complex_t (*avrData)(const Material&) = [](const Material& mat) {
69  return mat.materialData();
70  };
71  const complex_t avr_mat_data = averageData<complex_t>(layer_mat, regions, avrData);
72  return MaterialBySLD(avr_mat_name, avr_mat_data.real(), avr_mat_data.imag(), mag_avr);
73  } else
74  throw std::runtime_error("Error in CalculateAverageMaterial: unknown material type.");
75 }
MATERIAL_TYPES
std::complex< double > complex_t
Definition: Complex.h:20
Defines struct HomogeneousRegion, and declares fct createAveragedMaterial.
Defines class MaterialBySLDImpl.
Declares functions in namespace MaterialUtils.
Defines class RefractiveMaterialImpl.
Defines some unit conversion factors and other constants in namespace Units.
A wrapper for underlying material implementation.
Definition: Material.h:29
kvector_t magnetization() const
Get the magnetization (in A/m)
Definition: Material.cpp:79
std::string getName() const
Returns the name of material.
Definition: Material.cpp:69
complex_t materialData() const
Returns underlying material data.
Definition: Material.cpp:84
Material HomogeneousMaterial(const std::string &name, complex_t refractive_index, kvector_t magnetization)
Constructs a material with name, refractive_index and magnetization (in A/m).
Material createAveragedMaterial(const Material &layer_mat, const std::vector< HomogeneousRegion > &regions)
Creates averaged material.
Material MaterialBySLD()
MATERIAL_TYPES checkMaterialTypes(const std::vector< const Material * > &materials)
Checks if all non-default materials in materials are of the same type and returns this type.
T averageData(const Material &layer_mat, const std::vector< HomogeneousRegion > &regions, std::function< T(const Material &)> average)