BornAgain  1.19.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 reflection and scattering
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 auto constexpr rhoMconst = -PhysConsts::m_n * PhysConsts::g_factor_n * PhysConsts::mu_N
27 
28 class Options {
29 public:
30  int _NBilayers = 4;
31  double _angle = 0.;
32  double _magnetizationMagnitude = 1.e7;
33  double _thicknessFe = 100. * Units::angstrom;
34  double _thicknessNi = 40. * Units::angstrom;
35  double _sigmaRoughness = 0.;
36  int _effectiveSLD = 0;
37  RoughnessModel _roughnessModel = RoughnessModel::TANH;
38 
39  Options() {}
40  Options NBilayers(int n)
41  {
42  _NBilayers = n;
43  return *this;
44  }
45  Options angle(double angle)
46  {
47  _angle = angle;
48  return *this;
49  }
50  Options magnetizationMagnitude(double M)
51  {
52  _magnetizationMagnitude = M;
53  return *this;
54  }
55  Options thicknessFe(double t)
56  {
57  _thicknessFe = t;
58  return *this;
59  }
60  Options thicknessNi(double t)
61  {
62  _thicknessNi = t;
63  return *this;
64  }
65  Options sigmaRoughness(double r)
66  {
67  _sigmaRoughness = r;
68  return *this;
69  }
70  Options effectiveSLD(int i)
71  {
72  _effectiveSLD = i;
73  return *this;
74  }
75  Options roughnessModel(RoughnessModel rm)
76  {
77  _roughnessModel = rm;
78  return *this;
79  }
80 };
81 //! Creates the sample demonstrating an Fe-Ni Bilayer with and without roughness
82 //! @ingroup standard_samples
83 class FeNiBilayer {
84 public:
85  FeNiBilayer(Options opt = {})
86  : NBilayers(opt._NBilayers)
87  , angle(opt._angle)
88  , magnetizationMagnitude(opt._magnetizationMagnitude)
89  , thicknessFe(opt._thicknessFe)
90  , thicknessNi(opt._thicknessNi)
91  , sigmaRoughness(opt._sigmaRoughness)
92  , effectiveSLD(opt._effectiveSLD)
93  , roughnessModel(opt._roughnessModel)
94  {
95  if (angle != 0. && effectiveSLD != 0.)
96  throw std::runtime_error("Cannot perform scalar computation "
97  "for non-colinear magnetization");
98 
99  magnetizationVector = kvector_t(magnetizationMagnitude * std::sin(angle),
100  magnetizationMagnitude * std::cos(angle), 0);
101  sample = constructSample();
102  }
103 
104  MultiLayer* release() { return sample.release(); }
105 
106 private:
107  static constexpr auto sldFe = complex_t{8.02e-06, 0};
108  static constexpr auto sldAu = complex_t{4.6665e-6, 0};
109  static constexpr auto sldNi = complex_t{9.4245e-06, 0};
110 
111  int NBilayers;
112  double angle;
113  double magnetizationMagnitude;
114  double thicknessFe;
115  double thicknessNi;
116  double sigmaRoughness;
117  int effectiveSLD;
118  RoughnessModel roughnessModel;
119 
120  kvector_t magnetizationVector;
121 
122  std::unique_ptr<MultiLayer> sample;
123 
124  std::unique_ptr<MultiLayer> constructSample();
125 };
126 
127 } // namespace
128 
129 const complex_t FeNiBilayer::sldFe;
130 const complex_t FeNiBilayer::sldAu;
131 const complex_t FeNiBilayer::sldNi;
132 
133 std::unique_ptr<MultiLayer> FeNiBilayer::constructSample()
134 {
135  auto sample = std::make_unique<MultiLayer>();
136 
137  auto m_ambient = MaterialBySLD("Ambient", 0.0, 0.0);
138  auto m_Fe =
139  effectiveSLD == 0
140  ? MaterialBySLD("Fe", sldFe.real(), sldFe.imag(), magnetizationVector)
141  : MaterialBySLD("Fe", sldFe.real() + effectiveSLD * rhoMconst * magnetizationMagnitude,
142  sldFe.imag(), kvector_t{0, 0, 0});
143 
144  auto m_Ni = MaterialBySLD("Ni", sldNi.real(), sldNi.imag());
145  auto m_Substrate = MaterialBySLD("Au", sldAu.real(), sldAu.imag());
146 
147  Layer l_Fe{m_Fe, thicknessFe};
148  Layer l_Ni{m_Ni, thicknessNi};
149 
150  LayerRoughness roughness{sigmaRoughness, 0., 0.};
151  sample->addLayer(Layer{m_ambient});
152 
153  for (auto i = 0; i < NBilayers; ++i) {
154  sample->addLayerWithTopRoughness(l_Fe, roughness);
155  sample->addLayerWithTopRoughness(l_Ni, roughness);
156  }
157 
158  sample->addLayerWithTopRoughness(Layer{m_Substrate}, roughness);
159  sample->setRoughnessModel(roughnessModel);
160  return sample;
161 }
162 
164 {
165  auto sample = FeNiBilayer{Options()};
166  return sample.release();
167 }
168 
170 {
171  auto sample = FeNiBilayer{
172  Options().sigmaRoughness(2. * Units::angstrom).roughnessModel(RoughnessModel::TANH)};
173  return sample.release();
174 }
175 
177 {
178  auto sample = FeNiBilayer{
179  Options().sigmaRoughness(2. * Units::angstrom).roughnessModel(RoughnessModel::NEVOT_CROCE)};
180  return sample.release();
181 }
182 
184 {
185  auto sample = FeNiBilayer{Options().angle(38. * Units::deg)};
186  return sample.release();
187 }
188 
190 {
191  auto sample = FeNiBilayer{Options()
192  .angle(38 * Units::deg)
193  .sigmaRoughness(2. * Units::angstrom)
194  .roughnessModel(RoughnessModel::TANH)};
195  return sample.release();
196 }
197 
199 {
200  auto sample = FeNiBilayer{Options()
201  .angle(38 * Units::deg)
202  .sigmaRoughness(2. * Units::angstrom)
203  .roughnessModel(RoughnessModel::NEVOT_CROCE)};
204  return sample.release();
205 }
std::complex< double > complex_t
Definition: Complex.h:20
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)
Defines some unit conversion factors and other constants in namespace Units.
BasicVector3D< double > kvector_t
Definition: Vectors3D.h:21
MultiLayer * buildSample() const
MultiLayer * buildSample() const
MultiLayer * buildSample() const
MultiLayer * buildSample() const
A roughness of interface between two layers.
A layer in a MultiLayer sample.
Definition: Layer.h:27
Our sample model: a stack of layers one below the other.
Definition: MultiLayer.h:41
RoughnessModel roughnessModel() const
Definition: MultiLayer.h:66
Material MaterialBySLD()
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.
static constexpr double deg
Definition: Units.h:46
static constexpr double angstrom
Definition: Units.h:34