BornAgain  1.19.0
Simulate and fit neutron and x-ray scattering at grazing incidence
InterferenceFunctionItems.cpp
Go to the documentation of this file.
1 // ************************************************************************************************
2 //
3 // BornAgain: simulate and fit reflection and scattering
4 //
5 //! @file GUI/coregui/Models/InterferenceFunctionItems.cpp
6 //! @brief Implements InterferenceFunctionItems's classes
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"
23 
24 namespace {
25 const QString decay_function_tag = "Decay Function";
26 }
27 
28 // TODO (when back compatibility will be broken again)
29 // Make InterferenceFunction1DLatticeItem::P_DECAY_FUNCTION and
30 // InterferenceFunction2DLatticeItem::P_DECAY_FUNCTION rely on same constant
31 
33  QString::fromStdString("PositionVariance");
34 
36  : SessionGraphicsItem(modelType)
37 {
39  ->setToolTip("Variance of the position in each dimension (nm^2)");
40 }
41 
43 
45 {
47 }
48 
49 // --------------------------------------------------------------------------------------------- //
50 
51 const QString InterferenceFunction1DLatticeItem::P_LENGTH = QString::fromStdString("Length");
52 const QString InterferenceFunction1DLatticeItem::P_ROTATION_ANGLE = QString::fromStdString("Xi");
53 const QString InterferenceFunction1DLatticeItem::P_DECAY_FUNCTION = decay_function_tag;
54 
56  : InterferenceFunctionItem("Interference1DLattice")
57 {
58  setToolTip("Interference function of a 1D lattice");
59  addProperty(P_LENGTH, 20.0 * Units::nm)->setToolTip("Lattice length in nanometers");
61  ->setToolTip("Rotation of lattice with respect to x-axis of reference \n"
62  "frame (beam direction) in degrees ");
63  addGroupProperty(P_DECAY_FUNCTION, "Decay function 1D")
64  ->setToolTip("One-dimensional decay function (finite size effects)");
65 }
66 
67 std::unique_ptr<IInterferenceFunction>
69 {
70  auto result = std::make_unique<InterferenceFunction1DLattice>(
71  getItemValue(P_LENGTH).toDouble(),
73  auto pdfItem = dynamic_cast<FTDecayFunction1DItem*>(
75  result->setDecayFunction(*pdfItem->createFTDecayFunction());
76  setPositionVariance(result.get());
77  return std::unique_ptr<IInterferenceFunction>(result.release());
78 }
79 
80 // --------------------------------------------------------------------------------------------- //
81 
82 const QString InterferenceFunction2DLatticeItem::P_LATTICE_TYPE = "LatticeType";
83 const QString InterferenceFunction2DLatticeItem::P_DECAY_FUNCTION = decay_function_tag;
84 const QString InterferenceFunction2DLatticeItem::P_XI_INTEGRATION = "Integration_over_xi";
85 
87  : InterferenceFunctionItem("Interference2DLattice")
88 {
89  setToolTip("Interference function of a 2D lattice");
90  addGroupProperty(P_LATTICE_TYPE, "Lattice group")->setToolTip("Type of lattice");
91  addGroupProperty(P_DECAY_FUNCTION, "Decay function 2D")
92  ->setToolTip("Two-dimensional decay function (finite size effects)");
94  ->setToolTip("Enables/disables averaging over the lattice rotation angle.");
95 
96  mapper()->setOnPropertyChange([this](const QString& name) {
99  }
100  });
101  mapper()->setOnChildPropertyChange([this](SessionItem* item, const QString&) {
102  if (item->modelType() == "GroupProperty"
104  update_rotation_availability();
105  }
106  });
107 }
108 
109 std::unique_ptr<IInterferenceFunction>
111 {
112  auto& latticeItem = groupItem<Lattice2DItem>(P_LATTICE_TYPE);
113  std::unique_ptr<InterferenceFunction2DLattice> result(
114  new InterferenceFunction2DLattice(*latticeItem.createLattice()));
115 
116  auto& pdfItem = groupItem<FTDecayFunction2DItem>(P_DECAY_FUNCTION);
117  result->setDecayFunction(*pdfItem.createFTDecayFunction());
118  result->setIntegrationOverXi(getItemValue(P_XI_INTEGRATION).toBool());
119  setPositionVariance(result.get());
120 
121  return std::unique_ptr<IInterferenceFunction>(result.release());
122 }
123 
125 {
126  auto p_lattice_item = getGroupItem(P_LATTICE_TYPE);
127  if (p_lattice_item) {
128  auto angle_item = p_lattice_item->getItem(Lattice2DItem::P_LATTICE_ROTATION_ANGLE);
129  angle_item->setEnabled(!getItemValue(P_XI_INTEGRATION).toBool());
130  }
131 }
132 
133 // --------------------------------------------------------------------------------------------- //
134 
136  QString::fromStdString("DampingLength");
138  QString::fromStdString("DomainSize1");
140  QString::fromStdString("DomainSize2");
141 const QString InterferenceFunction2DParaCrystalItem::P_XI_INTEGRATION = "Integration_over_xi";
142 const QString InterferenceFunction2DParaCrystalItem::P_PDF1 = "PDF #1";
143 const QString InterferenceFunction2DParaCrystalItem::P_PDF2 = "PDF #2";
144 
146  : InterferenceFunctionItem("Interference2DParaCrystal")
147 {
148  setToolTip("Interference function of a two-dimensional paracrystal");
149 
151  ->setToolTip("Type of lattice");
154  ->setEnabled(false);
156  ->setToolTip("Enables/disables averaging over the lattice rotation angle.");
157 
159  ->setToolTip("The damping (coherence) length of the paracrystal in nanometers");
160 
162  ->setToolTip("Size of the coherent domain along the first basis vector in nanometers");
164  ->setToolTip("Size of the coherent domain along the second basis vector in nanometers");
165  addGroupProperty(P_PDF1, "PDF 2D")
166  ->setToolTip("Probability distribution in first lattice direction");
167  addGroupProperty(P_PDF2, "PDF 2D")
168  ->setToolTip("Probability distribution in second lattice direction");
169 
170  mapper()->setOnPropertyChange([this](const QString& name) {
173  }
174  });
175 
176  mapper()->setOnChildPropertyChange([this](SessionItem* item, const QString& property) {
177  if (item->modelType() == "GroupProperty"
179  update_rotation_availability();
180  }
181  if (item->modelType() == "GroupProperty" && property == GroupItem::T_ITEMS && isTag(P_PDF1)
182  && isTag(P_PDF2))
184  });
185 
187 }
188 
189 std::unique_ptr<IInterferenceFunction>
191 {
192  auto& latticeItem = groupItem<Lattice2DItem>(InterferenceFunction2DLatticeItem::P_LATTICE_TYPE);
193 
194  std::unique_ptr<InterferenceFunction2DParaCrystal> result(
195  new InterferenceFunction2DParaCrystal(*latticeItem.createLattice(), 0, 0, 0));
196 
197  result->setDampingLength(getItemValue(P_DAMPING_LENGTH).toDouble());
198  result->setDomainSizes(getItemValue(P_DOMAIN_SIZE1).toDouble(),
199  getItemValue(P_DOMAIN_SIZE2).toDouble());
200  result->setIntegrationOverXi(getItemValue(P_XI_INTEGRATION).toBool());
201 
202  auto& pdf1Item = groupItem<FTDistribution2DItem>(InterferenceFunction2DParaCrystalItem::P_PDF1);
203  auto& pdf2Item = groupItem<FTDistribution2DItem>(InterferenceFunction2DParaCrystalItem::P_PDF2);
204  result->setProbabilityDistributions(*pdf1Item.createFTDistribution(),
205  *pdf2Item.createFTDistribution());
206 
207  setPositionVariance(result.get());
208  return std::unique_ptr<IInterferenceFunction>(result.release());
209 }
210 
211 //! Sets rotation property of the lattice enabled/disabled depending on integration flag.
212 
214 {
216  if (p_lattice_item) {
217  auto angle_item = p_lattice_item->getItem(Lattice2DItem::P_LATTICE_ROTATION_ANGLE);
218  angle_item->setEnabled(!getItemValue(P_XI_INTEGRATION).toBool());
219  }
220 }
221 
223 {
224  GroupItem* group1 = dynamic_cast<GroupItem*>(getItem(P_PDF1));
225  GroupItem* group2 = dynamic_cast<GroupItem*>(getItem(P_PDF2));
226 
227  if (!group1 || !group2)
228  return;
229 
230  SessionItem* pdf1 = group1->currentItem();
231  SessionItem* pdf2 = group2->currentItem();
232 
233  if (pdf1 && pdf2) {
234  if (pdf1->modelType() == pdf2->modelType()) {
235  pdf1->setDisplayName(pdf1->modelType() + QString::number(0));
236  pdf2->setDisplayName(pdf2->modelType() + QString::number(1));
237  } else {
238  pdf1->setDisplayName(pdf1->modelType());
239  pdf2->setDisplayName(pdf2->modelType());
240  }
241  }
242 }
243 
244 // --------------------------------------------------------------------------------------------- //
245 
246 const QString InterferenceFunctionFinite2DLatticeItem::P_XI_INTEGRATION = "Integration_over_xi";
247 const QString InterferenceFunctionFinite2DLatticeItem::P_DOMAIN_SIZE_1 = "Domain_size_1";
248 const QString InterferenceFunctionFinite2DLatticeItem::P_DOMAIN_SIZE_2 = "Domain_size_2";
249 
251  : InterferenceFunctionItem("InterferenceFinite2DLattice")
252 {
253  setToolTip("Interference function of a finite 2D lattice");
255  ->setToolTip("Type of lattice");
257  ->setToolTip("Enables/disables averaging over the lattice rotation angle.");
258  addProperty(P_DOMAIN_SIZE_1, 100u)->setToolTip("Domain size 1 in number of unit cells");
259  addProperty(P_DOMAIN_SIZE_2, 100u)->setToolTip("Domain size 2 in number of unit cells");
260 
261  mapper()->setOnPropertyChange([this](const QString& name) {
264  }
265  });
266  mapper()->setOnChildPropertyChange([this](SessionItem* item, const QString&) {
267  if (item->modelType() == "GroupProperty"
269  update_rotation_availability();
270  }
271  });
272 }
273 
274 std::unique_ptr<IInterferenceFunction>
276 {
277  auto& latticeItem = groupItem<Lattice2DItem>(InterferenceFunction2DLatticeItem::P_LATTICE_TYPE);
278  auto size_1 = getItemValue(P_DOMAIN_SIZE_1).toUInt();
279  auto size_2 = getItemValue(P_DOMAIN_SIZE_2).toUInt();
280  std::unique_ptr<InterferenceFunctionFinite2DLattice> result(
281  new InterferenceFunctionFinite2DLattice(*latticeItem.createLattice(), size_1, size_2));
282 
283  result->setIntegrationOverXi(getItemValue(P_XI_INTEGRATION).toBool());
284  setPositionVariance(result.get());
285 
286  return std::unique_ptr<IInterferenceFunction>(result.release());
287 }
288 
290 {
292  if (p_lattice_item) {
293  auto angle_item = p_lattice_item->getItem(Lattice2DItem::P_LATTICE_ROTATION_ANGLE);
294  angle_item->setEnabled(!getItemValue(P_XI_INTEGRATION).toBool());
295  }
296 }
297 
298 // --------------------------------------------------------------------------------------------- //
299 
300 const QString InterferenceFunctionHardDiskItem::P_RADIUS = QString::fromStdString("Radius");
302  QString::fromStdString("TotalParticleDensity");
303 
305  : InterferenceFunctionItem("InterferenceHardDisk")
306 {
307  setToolTip("Interference function for hard disk Percus-Yevick");
308  addProperty(P_RADIUS, 5.0 * Units::nm)->setToolTip("Hard disk radius in nanometers");
309  addProperty(P_DENSITY, 0.002)->setToolTip("Particle density in particles per square nanometer");
310 }
311 
312 std::unique_ptr<IInterferenceFunction>
314 {
315  auto result = std::make_unique<InterferenceFunctionHardDisk>(
316  getItemValue(P_RADIUS).toDouble(), getItemValue(P_DENSITY).toDouble());
317  setPositionVariance(result.get());
318  return std::unique_ptr<IInterferenceFunction>(result.release());
319 }
320 
321 // --------------------------------------------------------------------------------------------- //
322 
324  QString::fromStdString("PeakDistance");
326  QString::fromStdString("DampingLength");
328  QString::fromStdString("DomainSize");
330  QString::fromStdString("SizeSpaceCoupling");
332 
334  : InterferenceFunctionItem("InterferenceRadialParaCrystal")
335 {
336  setToolTip("Interference function of a radial paracrystal");
338  ->setToolTip("Average distance to the next neighbor in nanometers");
340  ->setToolTip("The damping (coherence) length of the paracrystal "
341  "in nanometers");
343  ->setToolTip("Size of coherence domain along the lattice main axis "
344  "in nanometers");
345  addProperty(P_KAPPA, 0.0)
346  ->setToolTip("Size spacing coupling parameter of the Size Spacing "
347  "Correlation Approximation");
348  addGroupProperty(P_PDF, "PDF 1D")->setToolTip("One-dimensional probability distribution");
349 }
350 
351 std::unique_ptr<IInterferenceFunction>
353 {
354  auto result = std::make_unique<InterferenceFunctionRadialParaCrystal>(
355  getItemValue(P_PEAK_DISTANCE).toDouble(), getItemValue(P_DAMPING_LENGTH).toDouble());
356  result->setDomainSize(getItemValue(P_DOMAIN_SIZE).toDouble());
357  result->setKappa(getItemValue(P_KAPPA).toDouble());
358 
359  auto& pdfItem = groupItem<FTDistribution1DItem>(P_PDF);
360  result->setProbabilityDistribution(*pdfItem.createFTDistribution());
361  setPositionVariance(result.get());
362  return std::unique_ptr<IInterferenceFunction>(result.release());
363 }
Defines FTDecayFunction1DItem classes.
Defines FTDistribution1DItem's classes.
Defines class GroupItem.
Defines InterferenceFunctionItems's classes.
Includes all interference function definitions.
Defines classes Lattice2DItems.
Defines ModelPath namespace.
Defines some unit conversion factors and other constants in namespace Units.
SessionItem * currentItem() const
Definition: GroupItem.cpp:41
static const QString T_ITEMS
Definition: GroupItem.h:27
Abstract base class of interference functions.
void setPositionVariance(double var)
Sets the variance of the position for the calculation of the DW factor It is defined as the variance ...
std::unique_ptr< IInterferenceFunction > createInterferenceFunction() const
std::unique_ptr< IInterferenceFunction > createInterferenceFunction() const
Interference function of a 2D lattice.
std::unique_ptr< IInterferenceFunction > createInterferenceFunction() const
void update_rotation_availability()
Sets rotation property of the lattice enabled/disabled depending on integration flag.
Interference function of a 2D paracrystal.
std::unique_ptr< IInterferenceFunction > createInterferenceFunction() const
Interference function of a finite 2D lattice.
std::unique_ptr< IInterferenceFunction > createInterferenceFunction() const
static const QString P_POSITION_VARIANCE
void setPositionVariance(IInterferenceFunction *p_iff) const
virtual ~InterferenceFunctionItem()
InterferenceFunctionItem(const QString &modelType)
std::unique_ptr< IInterferenceFunction > createInterferenceFunction() const
static const QString P_LATTICE_ROTATION_ANGLE
void setOnChildPropertyChange(std::function< void(SessionItem *, QString)> f, const void *caller=0)
Calls back on child property change, report childItem and property name.
Definition: ModelMapper.cpp:49
void setOnPropertyChange(std::function< void(QString)> f, const void *caller=0)
Definition: ModelMapper.cpp:35
bool isTag(const QString &name) const
Returns true if tag is available.
SessionItem * addProperty(const QString &name, const QVariant &variant)
Add new property item and register new tag.
SessionItem * getGroupItem(const QString &groupName) const
Access subitem of group item.
QVariant getItemValue(const QString &tag) const
Directly access value of item under given tag.
void setDisplayName(const QString &display_name)
Set display name.
SessionItem * addGroupProperty(const QString &groupTag, const QString &groupType)
Creates new group item and register new tag, returns GroupItem.
ModelMapper * mapper()
Returns the current model mapper of this item. Creates new one if necessary.
T * item(const QString &tag) const
Definition: SessionItem.h:151
SessionItem & setToolTip(const QString &tooltip)
QString modelType() const
Get model type.
void setEnabled(bool enabled)
SessionItem * getItem(const QString &tag="", int row=0) const
Returns item in given row of given tag.
QString const & name(EShape k)
Definition: particles.cpp:21
double deg2rad(double angle)
Definition: Units.h:59
static constexpr double micrometer
Definition: Units.h:35
static constexpr double nm
Definition: Units.h:39