BornAgain  1.18.0
Simulate and fit neutron and x-ray scattering at grazing incidence
FeNiBilayerBuilder.cpp
Go to the documentation of this file.
1 // ************************************************************************** //
2 //
3 // BornAgain: simulate and fit scattering at grazing incidence
4 //
5 //! @file Sample/StandardSamples/FeNiBilayerBuilder.cpp
6 //! @brief Defines various sample builder classes to
7 //! test polarized specular computations
8 //!
9 //! @homepage http://www.bornagainproject.org
10 //! @license GNU General Public License v3 or higher (see COPYING)
11 //! @copyright Forschungszentrum Jülich GmbH 2020
12 //! @authors Scientific Computing Group at MLZ (see CITATION, AUTHORS)
13 //
14 // ************************************************************************** //
15 
18 #include "Base/Const/Units.h"
23 
24 namespace
25 {
26 auto constexpr rhoMconst = -PhysConsts::m_n * PhysConsts::g_factor_n * PhysConsts::mu_N
28 
29 class Options
30 {
31 public:
32  int _NBilayers = 4;
33  double _angle = 0.;
34  double _magnetizationMagnitude = 1.e7;
35  double _thicknessFe = 100. * Units::angstrom;
36  double _thicknessNi = 40. * Units::angstrom;
37  double _sigmaRoughness = 0.;
38  int _effectiveSLD = 0;
39  RoughnessModel _roughnessModel = RoughnessModel::TANH;
40 
41  Options() {}
42  Options NBilayers(int n)
43  {
44  _NBilayers = n;
45  return *this;
46  }
47  Options angle(double angle)
48  {
49  _angle = angle;
50  return *this;
51  }
52  Options magnetizationMagnitude(double M)
53  {
54  _magnetizationMagnitude = M;
55  return *this;
56  }
57  Options thicknessFe(double t)
58  {
59  _thicknessFe = t;
60  return *this;
61  }
62  Options thicknessNi(double t)
63  {
64  _thicknessNi = t;
65  return *this;
66  }
67  Options sigmaRoughness(double r)
68  {
69  _sigmaRoughness = r;
70  return *this;
71  }
72  Options effectiveSLD(int i)
73  {
74  _effectiveSLD = i;
75  return *this;
76  }
77  Options roughnessModel(RoughnessModel rm)
78  {
79  _roughnessModel = rm;
80  return *this;
81  }
82 };
83 //! Creates the sample demonstrating an Fe-Ni Bilayer with and without roughness
84 //! @ingroup standard_samples
85 class FeNiBilayer
86 {
87 public:
88  FeNiBilayer(Options opt = {})
89  : NBilayers(opt._NBilayers), angle(opt._angle),
90  magnetizationMagnitude(opt._magnetizationMagnitude), thicknessFe(opt._thicknessFe),
91  thicknessNi(opt._thicknessNi), sigmaRoughness(opt._sigmaRoughness),
92  effectiveSLD(opt._effectiveSLD), roughnessModel(opt._roughnessModel)
93  {
94  if (angle != 0. && effectiveSLD != 0.)
95  throw std::runtime_error("Cannot perform scalar computation "
96  "for non-colinear magnetization");
97 
98  magnetizationVector = kvector_t(magnetizationMagnitude * std::sin(angle),
99  magnetizationMagnitude * std::cos(angle), 0);
100  sample = constructSample();
101  }
102 
103  MultiLayer* release() { return sample.release(); }
104 
105 private:
106  static constexpr auto sldFe = complex_t{8.02e-06, 0};
107  static constexpr auto sldAu = complex_t{4.6665e-6, 0};
108  static constexpr auto sldNi = complex_t{9.4245e-06, 0};
109 
110  int NBilayers;
111  double angle;
112  double magnetizationMagnitude;
113  double thicknessFe;
114  double thicknessNi;
115  double sigmaRoughness;
116  int effectiveSLD;
117  RoughnessModel roughnessModel;
118 
119  kvector_t magnetizationVector;
120 
121  std::unique_ptr<MultiLayer> sample;
122 
123  std::unique_ptr<MultiLayer> constructSample();
124 };
125 
126 } // namespace
127 
128 const complex_t FeNiBilayer::sldFe;
129 const complex_t FeNiBilayer::sldAu;
130 const complex_t FeNiBilayer::sldNi;
131 
132 std::unique_ptr<MultiLayer> FeNiBilayer::constructSample()
133 {
134  auto sample = std::make_unique<MultiLayer>();
135 
136  auto m_ambient = MaterialBySLD("Ambient", 0.0, 0.0);
137  auto m_Fe =
138  effectiveSLD == 0
139  ? MaterialBySLD("Fe", sldFe.real(), sldFe.imag(), magnetizationVector)
140  : MaterialBySLD("Fe", sldFe.real() + effectiveSLD * rhoMconst * magnetizationMagnitude,
141  sldFe.imag(), kvector_t{0, 0, 0});
142 
143  auto m_Ni = MaterialBySLD("Ni", sldNi.real(), sldNi.imag());
144  auto m_Substrate = MaterialBySLD("Au", sldAu.real(), sldAu.imag());
145 
146  Layer l_Fe{m_Fe, thicknessFe};
147  Layer l_Ni{m_Ni, thicknessNi};
148 
149  LayerRoughness roughness{sigmaRoughness, 0., 0.};
150  sample->addLayer(Layer{m_ambient});
151 
152  for (auto i = 0; i < NBilayers; ++i) {
153  sample->addLayerWithTopRoughness(l_Fe, roughness);
154  sample->addLayerWithTopRoughness(l_Ni, roughness);
155  }
156 
157  sample->addLayerWithTopRoughness(Layer{m_Substrate}, roughness);
158  sample->setRoughnessModel(roughnessModel);
159  return sample;
160 }
161 
162 MultiLayer* FeNiBilayerBuilder::buildSample() const
163 {
164  auto sample = FeNiBilayer{Options()};
165  return sample.release();
166 }
167 
168 MultiLayer* FeNiBilayerTanhBuilder::buildSample() const
169 {
170  auto sample = FeNiBilayer{
171  Options().sigmaRoughness(2. * Units::angstrom).roughnessModel(RoughnessModel::TANH)};
172  return sample.release();
173 }
174 
175 MultiLayer* FeNiBilayerNCBuilder::buildSample() const
176 {
177  auto sample = FeNiBilayer{
178  Options().sigmaRoughness(2. * Units::angstrom).roughnessModel(RoughnessModel::NEVOT_CROCE)};
179  return sample.release();
180 }
181 
182 MultiLayer* FeNiBilayerSpinFlipBuilder::buildSample() const
183 {
184  auto sample = FeNiBilayer{Options().angle(38. * Units::degree)};
185  return sample.release();
186 }
187 
188 MultiLayer* FeNiBilayerSpinFlipTanhBuilder::buildSample() const
189 {
190  auto sample = FeNiBilayer{Options()
191  .angle(38 * Units::degree)
192  .sigmaRoughness(2. * Units::angstrom)
193  .roughnessModel(RoughnessModel::TANH)};
194  return sample.release();
195 }
196 
197 MultiLayer* FeNiBilayerSpinFlipNCBuilder::buildSample() const
198 {
199  auto sample = FeNiBilayer{Options()
200  .angle(38 * Units::degree)
201  .sigmaRoughness(2. * Units::angstrom)
202  .roughnessModel(RoughnessModel::NEVOT_CROCE)};
203  return sample.release();
204 }
Defines various sample builder classes to test polarized specular computations.
Defines class LayerRoughness.
Defines class Layer.
Factory functions used to create material instances.
Defines class MultiLayer.
Defines the values of physical constants (SI)
constexpr double g_factor_n
neutron g-factor
constexpr double h_bar
Reduced Plank constant, J s.
constexpr double m_n
Neutron mass, kg.
constexpr double mu_N
Nuclear magneton ( ), J/T.
Defines some unit conversion factors and other constants in namespace Units.
A roughness of interface between two layers.
A layer, with thickness (in nanometer) and material.
Definition: Layer.h:28
Our sample model: a stack of layers one below the other.
Definition: MultiLayer.h:42