BornAgain  1.19.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 reflection and scattering
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 template <class T>
25 T averageData(const Material& layer_mat, const std::vector<HomogeneousRegion>& regions,
26  std::function<T(const Material&)> average)
27 {
28  const T layer_data = average(layer_mat);
29  T averaged_data = layer_data;
30  for (const auto& region : regions)
31  averaged_data += region.m_volume * (average(region.m_material) - layer_data);
32  return averaged_data;
33 }
34 
35 } // namespace
36 
38  const std::vector<HomogeneousRegion>& regions)
39 {
40  // determine the type of returned material
41  std::vector<const Material*> materials(regions.size() + 1);
42  materials[0] = &layer_mat;
43  for (size_t i = 0, regions_size = regions.size(); i < regions_size; ++i)
44  materials[i + 1] = &regions[i].m_material;
45  const MATERIAL_TYPES avr_material_type = MaterialUtils::checkMaterialTypes(materials);
46  if (avr_material_type == MATERIAL_TYPES::InvalidMaterialType)
47  throw std::runtime_error("Error in createAveragedMaterial(): non-default materials of "
48  "different types used simultaneously.");
49 
50  // create the name of returned material
51  const std::string avr_mat_name = layer_mat.getName() + "_avg";
52 
53  // calculate averaged magnetization
54  const kvector_t mag_avr = averageData<kvector_t>(
55  layer_mat, regions, [](const Material& mat) { return mat.magnetization(); });
56 
57  if (avr_material_type == MATERIAL_TYPES::RefractiveMaterial) {
58  // avrData returns (1 - mdc)^2 - 1, where mdc is material data conjugate
59  auto avrData = [](const Material& mat) -> complex_t {
60  const complex_t mdc = std::conj(mat.materialData());
61  return mdc * mdc - 2.0 * mdc;
62  };
63  const complex_t avr_mat_data =
64  std::conj(1.0 - std::sqrt(1.0 + averageData<complex_t>(layer_mat, regions, avrData)));
65  return HomogeneousMaterial(avr_mat_name, avr_mat_data.real(), avr_mat_data.imag(), mag_avr);
66  } else if (avr_material_type == MATERIAL_TYPES::MaterialBySLD) {
67  complex_t (*avrData)(const Material&) = [](const Material& mat) {
68  return mat.materialData();
69  };
70  const complex_t avr_mat_data = averageData<complex_t>(layer_mat, regions, avrData);
71  return MaterialBySLD(avr_mat_name, avr_mat_data.real(), avr_mat_data.imag(), mag_avr);
72  } else
73  throw std::runtime_error("Error in CalculateAverageMaterial: unknown material type.");
74 }
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:76
std::string getName() const
Returns the name of material.
Definition: Material.cpp:66
complex_t materialData() const
Returns underlying material data.
Definition: Material.cpp:81
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.