BornAgain  1.19.79
Simulate and fit neutron and x-ray scattering at grazing incidence
ItemizeSample.cpp
Go to the documentation of this file.
1 // ************************************************************************************************
2 //
3 // BornAgain: simulate and fit reflection and scattering
4 //
5 //! @file GUI/Model/FromCore/ItemizeSample.cpp
6 //! @brief Implements class GUISampleBuilder
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"
27 #include "GUI/Util/Error.h"
28 #include "Param/Node/NodeUtils.h"
29 #include "Sample/Aggregate/Interferences.h"
30 #include "Sample/Aggregate/ParticleLayout.h"
31 #include "Sample/HardParticle/HardParticles.h"
32 #include "Sample/Interface/LayerInterface.h"
33 #include "Sample/Interface/LayerRoughness.h"
34 #include "Sample/Multilayer/Layer.h"
35 #include "Sample/Multilayer/MultiLayer.h"
36 #include "Sample/Particle/Crystal.h"
37 #include "Sample/Particle/MesoCrystal.h"
38 #include "Sample/Particle/Particle.h"
39 #include "Sample/Particle/ParticleCoreShell.h"
40 #include "Sample/Scattering/Rotations.h"
41 
42 using NodeUtils::ChildNodesOfType;
43 using NodeUtils::OnlyChildOfType;
44 
45 namespace {
46 
47 void setPDF1D(InterferenceRadialParaCrystalItem* item, const IProfile1D* ipdf)
48 {
49  if (const auto* pdf = dynamic_cast<const Profile1DCauchy*>(ipdf)) {
50  auto* pdfItem = new Profile1DCauchyItem();
51  pdfItem->omega().set(pdf->omega());
52  item->setPDFType(pdfItem);
53  } else if (const auto* pdf = dynamic_cast<const Profile1DGauss*>(ipdf)) {
54  auto* pdfItem = new Profile1DGaussItem();
55  pdfItem->omega().set(pdf->omega());
56  item->setPDFType(pdfItem);
57  } else if (const auto* pdf = dynamic_cast<const Profile1DGate*>(ipdf)) {
58  auto* pdfItem = new Profile1DGateItem();
59  pdfItem->omega().set(pdf->omega());
60  item->setPDFType(pdfItem);
61  } else if (const auto* pdf = dynamic_cast<const Profile1DTriangle*>(ipdf)) {
62  auto* pdfItem = new Profile1DTriangleItem();
63  pdfItem->omega().set(pdf->omega());
64  item->setPDFType(pdfItem);
65  } else if (const auto* pdf = dynamic_cast<const Profile1DCosine*>(ipdf)) {
66  auto* pdfItem = new Profile1DCosineItem();
67  pdfItem->omega().set(pdf->omega());
68  item->setPDFType(pdfItem);
69  } else if (const auto* pdf = dynamic_cast<const Profile1DVoigt*>(ipdf)) {
70  auto* pdfItem = new Profile1DVoigtItem();
71  pdfItem->omega().set(pdf->omega());
72  pdfItem->eta().set(pdf->eta());
73  item->setPDFType(pdfItem);
74  } else
75  throw Error("GUI::Transform::FromCore::setPDF1D: -> Error");
76 }
77 
78 // note: SetterPDF(1|2)Type are needed because template template parameter must be classes
79 
80 template <class T>
81 struct SetterPDF1Type {
82  T* operator()(Interference2DParaCrystalItem* item)
83  {
84  auto* p = new T();
85  item->setPDF1Type(p);
86  return p;
87  }
88 };
89 
90 template <class T>
91 struct SetterPDF2Type {
92  T* operator()(Interference2DParaCrystalItem* item)
93  {
94  auto* p = new T();
95  item->setPDF2Type(p);
96  return p;
97  }
98 };
99 
100 template <template <class T> class setType>
101 void setPDF2D(Interference2DParaCrystalItem* item, const IProfile2D* pdf)
102 {
103  if (const auto* pdf_cauchy = dynamic_cast<const Profile2DCauchy*>(pdf)) {
104  Profile2DCauchyItem* pdfItem = setType<Profile2DCauchyItem>()(item);
105  pdfItem->setOmegaX(pdf_cauchy->omegaX());
106  pdfItem->setOmegaY(pdf_cauchy->omegaY());
107  pdfItem->setGamma(Units::rad2deg(pdf_cauchy->gamma()));
108  } else if (const auto* pdf_gauss = dynamic_cast<const Profile2DGauss*>(pdf)) {
109  Profile2DGaussItem* pdfItem = setType<Profile2DGaussItem>()(item);
110  pdfItem->setOmegaX(pdf_gauss->omegaX());
111  pdfItem->setOmegaY(pdf_gauss->omegaY());
112  pdfItem->setGamma(Units::rad2deg(pdf_gauss->gamma()));
113  } else if (const auto* pdf_gate = dynamic_cast<const Profile2DGate*>(pdf)) {
114  Profile2DGateItem* pdfItem = setType<Profile2DGateItem>()(item);
115  pdfItem->setOmegaX(pdf_gate->omegaX());
116  pdfItem->setOmegaY(pdf_gate->omegaY());
117  pdfItem->setGamma(Units::rad2deg(pdf_gate->gamma()));
118  } else if (const auto* pdf_cone = dynamic_cast<const Profile2DCone*>(pdf)) {
119  Profile2DConeItem* pdfItem = setType<Profile2DConeItem>()(item);
120  pdfItem->setOmegaX(pdf_cone->omegaX());
121  pdfItem->setOmegaY(pdf_cone->omegaY());
122  pdfItem->setGamma(Units::rad2deg(pdf_cone->gamma()));
123  } else if (const auto* pdf_voigt = dynamic_cast<const Profile2DVoigt*>(pdf)) {
124  Profile2DVoigtItem* pdfItem = setType<Profile2DVoigtItem>()(item);
125  pdfItem->setOmegaX(pdf_voigt->omegaX());
126  pdfItem->setOmegaY(pdf_voigt->omegaY());
127  pdfItem->setGamma(Units::rad2deg(pdf_voigt->gamma()));
128  pdfItem->setEta(pdf_voigt->eta());
129  } else
130  throw Error("GUI::Transform::FromCore::setPDF2D: -> Error");
131 }
132 
133 void setDecayFunction1D(Interference1DLatticeItem* item, const IProfile1D* ipdf)
134 {
135  if (const auto* pdf = dynamic_cast<const Profile1DCauchy*>(ipdf)) {
136  auto* pdfItem = new Profile1DCauchyItem();
137  pdfItem->omega().set(pdf->omega());
138  item->setDecayFunction(pdfItem);
139  } else if (const auto* pdf = dynamic_cast<const Profile1DGauss*>(ipdf)) {
140  auto* pdfItem = new Profile1DGaussItem();
141  pdfItem->omega().set(pdf->omega());
142  item->setDecayFunction(pdfItem);
143  } else if (const auto* pdf = dynamic_cast<const Profile1DTriangle*>(ipdf)) {
144  auto* pdfItem = new Profile1DTriangleItem();
145  pdfItem->omega().set(pdf->omega());
146  item->setDecayFunction(pdfItem);
147  } else if (const auto* pdf = dynamic_cast<const Profile1DVoigt*>(ipdf)) {
148  auto* pdfItem = new Profile1DVoigtItem();
149  pdfItem->omega().set(pdf->omega());
150  pdfItem->eta().set(pdf->eta());
151  item->setDecayFunction(pdfItem);
152  } else
153  throw Error("GUI::Transform::FromCore::setDecayFunction1D: -> Error");
154 }
155 
156 void setDecayFunction2D(Interference2DLatticeItem* item, const IProfile2D* pdf)
157 {
158  if (const auto* pdf_cauchy = dynamic_cast<const Profile2DCauchy*>(pdf)) {
159  auto* pdfItem = new Profile2DCauchyItem();
160  pdfItem->setOmegaX(pdf_cauchy->omegaX());
161  pdfItem->setOmegaY(pdf_cauchy->omegaY());
162  pdfItem->setGamma(Units::rad2deg(pdf_cauchy->gamma()));
163  item->setDecayFunctionType(pdfItem);
164  } else if (const auto* pdf_gauss = dynamic_cast<const Profile2DGauss*>(pdf)) {
165  auto* pdfItem = new Profile2DGaussItem();
166  pdfItem->setOmegaX(pdf_gauss->omegaX());
167  pdfItem->setOmegaY(pdf_gauss->omegaY());
168  pdfItem->setGamma(Units::rad2deg(pdf_gauss->gamma()));
169  item->setDecayFunctionType(pdfItem);
170  } else if (const auto* pdf_voigt = dynamic_cast<const Profile2DVoigt*>(pdf)) {
171  auto* pdfItem = new Profile2DVoigtItem();
172  pdfItem->setOmegaX(pdf_voigt->omegaX());
173  pdfItem->setOmegaY(pdf_voigt->omegaY());
174  pdfItem->setGamma(Units::rad2deg(pdf_voigt->gamma()));
175  pdfItem->setEta(pdf_voigt->eta());
176  item->setDecayFunctionType(pdfItem);
177  } else
178  throw Error("GUI::Transform::FromCore::setDecayFunction2D: -> Error");
179 }
180 
181 void set2DLatticeParameters(Interference2DAbstractLatticeItem* item, const Lattice2D& lattice)
182 {
183  Lattice2DItem* latticeItem(nullptr);
184  if (lattice.className() == "SquareLattice2D") {
185  auto* squareLatticeItem = new SquareLattice2DItem();
186  squareLatticeItem->setLatticeLength(lattice.length1());
187  latticeItem = squareLatticeItem;
188  } else if (lattice.className() == "HexagonalLattice2D") {
189  auto* hexLatticeItem = new HexagonalLattice2DItem();
190  hexLatticeItem->setLatticeLength(lattice.length1());
191  latticeItem = hexLatticeItem;
192  } else {
193  auto* basicLatticeItem = new BasicLattice2DItem();
194  basicLatticeItem->setLatticeLength1(lattice.length1());
195  basicLatticeItem->setLatticeLength2(lattice.length2());
196  basicLatticeItem->setLatticeAngle(Units::rad2deg(lattice.latticeAngle()));
197  latticeItem = basicLatticeItem;
198  }
199  latticeItem->setLatticeRotationAngle(Units::rad2deg(lattice.rotationAngle()));
200  item->setLatticeType(latticeItem);
201 }
202 
203 void setPositionVariance(InterferenceItem* item, const IInterference& iff)
204 {
205  double pos_var = iff.positionVariance();
206  item->positionVariance().set(pos_var);
207 }
208 
209 template <typename T>
210 T* addFormFactorItem(std::variant<ParticleItem*, MesoCrystalItem*> parent)
211 {
212  if (std::holds_alternative<ParticleItem*>(parent))
213  return std::get<ParticleItem*>(parent)->setFormFactorType<T>();
214 
215  return std::get<MesoCrystalItem*>(parent)->setOuterShapeType<T>();
216 }
217 
218 void set1DLatticeItem(Interference1DLatticeItem* item, const Interference1DLattice& sample)
219 {
220  item->length().set(sample.length());
221  item->rotationAngle().set(Units::rad2deg(sample.xi()));
222 
223  const auto* pdf = OnlyChildOfType<IProfile1D>(sample);
224  setDecayFunction1D(item, pdf);
225  setPositionVariance(item, sample);
226 }
227 
228 void set2DLatticeItem(Interference2DLatticeItem* item, const Interference2DLattice& sample)
229 {
230  set2DLatticeParameters(item, sample.lattice());
231 
232  item->setXiIntegration(sample.integrationOverXi());
233 
234  const auto* p_pdf = OnlyChildOfType<IProfile2D>(sample);
235  setDecayFunction2D(item, p_pdf);
236  setPositionVariance(item, sample);
237 }
238 
239 void set2DParaCrystalItem(Interference2DParaCrystalItem* item,
240  const Interference2DParaCrystal& sample)
241 {
242  set2DLatticeParameters(item, sample.lattice());
243 
244  item->setDampingLength(sample.dampingLength());
245  item->setDomainSize1(sample.domainSizes()[0]);
246  item->setDomainSize2(sample.domainSizes()[1]);
247  item->setXiIntegration(sample.integrationOverXi());
248 
249  auto pdfs = ChildNodesOfType<IProfile2D>(sample);
250 
251  if (!pdfs.empty()) {
252  setPDF2D<SetterPDF1Type>(item, pdfs[0]);
253  if (pdfs.size() >= 2)
254  setPDF2D<SetterPDF2Type>(item, pdfs[1]);
255  }
256  setPositionVariance(item, sample);
257 }
258 
259 void setFinite2DLatticeItem(InterferenceFinite2DLatticeItem* item,
260  const InterferenceFinite2DLattice& sample)
261 {
262  set2DLatticeParameters(item, sample.lattice());
263 
264  item->setDomainSize1(sample.numberUnitCells1());
265  item->setDomainSize2(sample.numberUnitCells2());
266  item->setXiIntegration(sample.integrationOverXi());
267  setPositionVariance(item, sample);
268 }
269 
270 void setHardDiskItem(InterferenceHardDiskItem* item, const InterferenceHardDisk& sample)
271 {
272  item->radius().set(sample.radius());
273  item->density().set(sample.density());
274  setPositionVariance(item, sample);
275 }
276 
277 void setRadialParaCrystalItem(InterferenceRadialParaCrystalItem* item,
278  const InterferenceRadialParaCrystal& sample)
279 {
280  item->peakDistance().set(sample.peakDistance());
281  item->dampingLength().set(sample.dampingLength());
282  item->domainSize().set(sample.domainSize());
283  item->kappa().set(sample.kappa());
284 
285  const auto* ipdf = OnlyChildOfType<IProfile1D>(sample);
286  setPDF1D(item, ipdf);
287  setPositionVariance(item, sample);
288 }
289 
290 //! Returns true if given roughness is non-zero roughness
291 bool isValidRoughness(const LayerRoughness* roughness)
292 {
293  if (!roughness)
294  return false;
295  if (roughness->sigma() == 0 && roughness->hurst() == 0.0
296  && roughness->lateralCorrLength() == 0.0)
297  return false;
298  return true;
299 }
300 
301 void setRoughnessItem(LayerBasicRoughnessItem* item, const LayerRoughness& sample)
302 {
303  item->sigma().set(sample.sigma());
304  item->hurst().set(sample.hurst());
305  item->lateralCorrelationLength().set(sample.lateralCorrLength());
306 }
307 
308 void setLayerItem(LayerItem* layerItem, const Layer* layer, const LayerInterface* top_interface)
309 {
310  layerItem->thickness().set(layer->thickness());
311  layerItem->clearRoughness();
312  layerItem->numSlices().set(layer->numberOfSlices());
313 
314  if (top_interface) {
315  const LayerRoughness* roughness = top_interface->roughness();
316  if (isValidRoughness(roughness)) {
317  layerItem->setBasicRoughness();
318  setRoughnessItem(layerItem->roughness().currentItem(), *roughness);
319  }
320  }
321 }
322 
323 void setRotation(ItemWithParticles* item, const IRotation* rotation)
324 {
325  if (!rotation)
326  item->setRotation(nullptr);
327  else if (const auto* r = dynamic_cast<const RotationX*>(rotation)) {
328  auto* rotationItem = new XRotationItem();
329  rotationItem->angle().set(Units::rad2deg(r->angle()));
330  item->setRotation(rotationItem);
331  } else if (const auto* r = dynamic_cast<const RotationY*>(rotation)) {
332  auto* rotationItem = new YRotationItem();
333  rotationItem->angle().set(Units::rad2deg(r->angle()));
334  item->setRotation(rotationItem);
335  } else if (const auto* r = dynamic_cast<const RotationZ*>(rotation)) {
336  auto* rotationItem = new ZRotationItem();
337  rotationItem->angle().set(Units::rad2deg(r->angle()));
338  item->setRotation(rotationItem);
339  } else if (const auto* r = dynamic_cast<const RotationEuler*>(rotation)) {
340  auto* rotationItem = new EulerRotationItem();
341  rotationItem->alpha().set(Units::rad2deg(r->alpha()));
342  rotationItem->beta().set(Units::rad2deg(r->beta()));
343  rotationItem->gamma().set(Units::rad2deg(r->gamma()));
344  item->setRotation(rotationItem);
345  }
346 }
347 
348 void setInterference(ParticleLayoutItem* layoutItem, const IInterference* interference)
349 {
350  if (!interference)
351  layoutItem->removeInterference();
352  else if (const auto* itf = dynamic_cast<const Interference1DLattice*>(interference)) {
353  auto* itfItem = new Interference1DLatticeItem();
354  set1DLatticeItem(itfItem, *itf);
355  layoutItem->setInterference(itfItem);
356  } else if (const auto* itf = dynamic_cast<const Interference2DLattice*>(interference)) {
357  auto* itfItem = new Interference2DLatticeItem();
358  set2DLatticeItem(itfItem, *itf);
359  layoutItem->setInterference(itfItem);
360  } else if (const auto* itf = dynamic_cast<const Interference2DParaCrystal*>(interference)) {
361  auto* itfItem = new Interference2DParaCrystalItem();
362  set2DParaCrystalItem(itfItem, *itf);
363  layoutItem->setInterference(itfItem);
364  } else if (const auto* itf = dynamic_cast<const InterferenceFinite2DLattice*>(interference)) {
365  auto* itfItem = new InterferenceFinite2DLatticeItem();
366  setFinite2DLatticeItem(itfItem, *itf);
367  layoutItem->setInterference(itfItem);
368  } else if (const auto* itf = dynamic_cast<const InterferenceHardDisk*>(interference)) {
369  auto* itfItem = new InterferenceHardDiskItem();
370  setHardDiskItem(itfItem, *itf);
371  layoutItem->setInterference(itfItem);
372  } else if (const auto* itf = dynamic_cast<const InterferenceRadialParaCrystal*>(interference)) {
373  auto* itfItem = new InterferenceRadialParaCrystalItem();
374  setRadialParaCrystalItem(itfItem, *itf);
375  layoutItem->setInterference(itfItem);
376  } else
377  ASSERT(false); // missing implementation for interference type
378 }
379 
380 void setFormFactor(std::variant<ParticleItem*, MesoCrystalItem*> parent,
381  const IFormFactor* iFormFactor)
382 {
383  if (const auto* formfactor = dynamic_cast<const Pyramid2*>(iFormFactor)) {
384  auto* formfactorItem = addFormFactorItem<Pyramid2Item>(parent);
385  formfactorItem->setLength(formfactor->length());
386  formfactorItem->setWidth(formfactor->width());
387  formfactorItem->setHeight(formfactor->height());
388  formfactorItem->setAlpha(Units::rad2deg(formfactor->alpha()));
389  } else if (const auto* formfactor = dynamic_cast<const BarGauss*>(iFormFactor)) {
390  auto* formfactorItem = addFormFactorItem<BarGaussItem>(parent);
391  formfactorItem->setLength(formfactor->length());
392  formfactorItem->setWidth(formfactor->width());
393  formfactorItem->setHeight(formfactor->height());
394  } else if (const auto* formfactor = dynamic_cast<const BarLorentz*>(iFormFactor)) {
395  auto* formfactorItem = addFormFactorItem<BarLorentzItem>(parent);
396  formfactorItem->setLength(formfactor->length());
397  formfactorItem->setWidth(formfactor->width());
398  formfactorItem->setHeight(formfactor->height());
399  } else if (const auto* formfactor = dynamic_cast<const Box*>(iFormFactor)) {
400  auto* formfactorItem = addFormFactorItem<BoxItem>(parent);
401  formfactorItem->setLength(formfactor->length());
402  formfactorItem->setWidth(formfactor->width());
403  formfactorItem->setHeight(formfactor->height());
404  } else if (const auto* formfactor = dynamic_cast<const Cone*>(iFormFactor)) {
405  auto* formfactorItem = addFormFactorItem<ConeItem>(parent);
406  formfactorItem->setRadius(formfactor->radius());
407  formfactorItem->setHeight(formfactor->height());
408  formfactorItem->setAlpha(Units::rad2deg(formfactor->alpha()));
409  } else if (const auto* formfactor = dynamic_cast<const Pyramid6*>(iFormFactor)) {
410  auto* formfactorItem = addFormFactorItem<Pyramid6Item>(parent);
411  formfactorItem->setBaseEdge(formfactor->baseEdge());
412  formfactorItem->setHeight(formfactor->height());
413  formfactorItem->setAlpha(Units::rad2deg(formfactor->alpha()));
414  } else if (const auto* formfactor = dynamic_cast<const Bipyramid4*>(iFormFactor)) {
415  auto* formfactorItem = addFormFactorItem<Bipyramid4Item>(parent);
416  formfactorItem->setLength(formfactor->length());
417  formfactorItem->setHeight(formfactor->height());
418  formfactorItem->setHeightRatio(formfactor->heightRatio());
419  formfactorItem->setAlpha(Units::rad2deg(formfactor->alpha()));
420  } else if (const auto* formfactor = dynamic_cast<const Cylinder*>(iFormFactor)) {
421  auto* formfactorItem = addFormFactorItem<CylinderItem>(parent);
422  formfactorItem->setRadius(formfactor->radius());
423  formfactorItem->setHeight(formfactor->height());
424  } else if (const auto* formfactor = dynamic_cast<const Dodecahedron*>(iFormFactor)) {
425  auto* formfactorItem = addFormFactorItem<DodecahedronItem>(parent);
426  formfactorItem->setEdge(formfactor->edge());
427  } else if (const auto* formfactor = dynamic_cast<const EllipsoidalCylinder*>(iFormFactor)) {
428  auto* formfactorItem = addFormFactorItem<EllipsoidalCylinderItem>(parent);
429  formfactorItem->setRadiusX(formfactor->radiusX());
430  formfactorItem->setRadiusY(formfactor->radiusY());
431  formfactorItem->setHeight(formfactor->height());
432  } else if (const auto* formfactor = dynamic_cast<const Sphere*>(iFormFactor)) {
433  auto* formfactorItem = addFormFactorItem<SphereItem>(parent);
434  formfactorItem->setRadius(formfactor->radius());
435  } else if (const auto* formfactor = dynamic_cast<const Spheroid*>(iFormFactor)) {
436  auto* formfactorItem = addFormFactorItem<SpheroidItem>(parent);
437  formfactorItem->setRadius(formfactor->radius());
438  formfactorItem->setHeight(formfactor->height());
439  } else if (const auto* formfactor = dynamic_cast<const Icosahedron*>(iFormFactor)) {
440  auto* formfactorItem = addFormFactorItem<IcosahedronItem>(parent);
441  formfactorItem->setEdge(formfactor->edge());
442  } else if (const auto* formfactor = dynamic_cast<const HemiEllipsoid*>(iFormFactor)) {
443  auto* formfactorItem = addFormFactorItem<HemiEllipsoidItem>(parent);
444  formfactorItem->setRadiusX(formfactor->radiusX());
445  formfactorItem->setRadiusY(formfactor->radiusY());
446  formfactorItem->setHeight(formfactor->height());
447  } else if (const auto* formfactor = dynamic_cast<const Prism3*>(iFormFactor)) {
448  auto* formfactorItem = addFormFactorItem<Prism3Item>(parent);
449  formfactorItem->setBaseEdge(formfactor->baseEdge());
450  formfactorItem->setHeight(formfactor->height());
451  } else if (const auto* formfactor = dynamic_cast<const Prism6*>(iFormFactor)) {
452  auto* formfactorItem = addFormFactorItem<Prism6Item>(parent);
453  formfactorItem->setBaseEdge(formfactor->baseEdge());
454  formfactorItem->setHeight(formfactor->height());
455  } else if (const auto* formfactor = dynamic_cast<const Pyramid4*>(iFormFactor)) {
456  auto* formfactorItem = addFormFactorItem<Pyramid4Item>(parent);
457  formfactorItem->setBaseEdge(formfactor->baseEdge());
458  formfactorItem->setHeight(formfactor->height());
459  formfactorItem->setAlpha(Units::rad2deg(formfactor->alpha()));
460  } else if (const auto* formfactor = dynamic_cast<const CosineRippleBox*>(iFormFactor)) {
461  auto* formfactorItem = addFormFactorItem<CosineRippleBoxItem>(parent);
462  formfactorItem->setLength(formfactor->length());
463  formfactorItem->setWidth(formfactor->width());
464  formfactorItem->setHeight(formfactor->height());
465  } else if (const auto* formfactor = dynamic_cast<const CosineRippleGauss*>(iFormFactor)) {
466  auto* formfactorItem = addFormFactorItem<CosineRippleGaussItem>(parent);
467  formfactorItem->setLength(formfactor->length());
468  formfactorItem->setWidth(formfactor->width());
469  formfactorItem->setHeight(formfactor->height());
470  } else if (const auto* formfactor = dynamic_cast<const CosineRippleLorentz*>(iFormFactor)) {
471  auto* formfactorItem = addFormFactorItem<CosineRippleLorentzItem>(parent);
472  formfactorItem->setLength(formfactor->length());
473  formfactorItem->setWidth(formfactor->width());
474  formfactorItem->setHeight(formfactor->height());
475  } else if (const auto* formfactor = dynamic_cast<const SawtoothRippleBox*>(iFormFactor)) {
476  auto* formfactorItem = addFormFactorItem<SawtoothRippleBoxItem>(parent);
477  formfactorItem->setLength(formfactor->length());
478  formfactorItem->setWidth(formfactor->width());
479  formfactorItem->setHeight(formfactor->height());
480  formfactorItem->setAsymmetry(formfactor->asymmetry());
481  } else if (const auto* formfactor = dynamic_cast<const SawtoothRippleGauss*>(iFormFactor)) {
482  auto* formfactorItem = addFormFactorItem<SawtoothRippleGaussItem>(parent);
483  formfactorItem->setLength(formfactor->length());
484  formfactorItem->setWidth(formfactor->width());
485  formfactorItem->setHeight(formfactor->height());
486  formfactorItem->setAsymmetry(formfactor->asymmetry());
487  } else if (const auto* formfactor = dynamic_cast<const SawtoothRippleLorentz*>(iFormFactor)) {
488  auto* formfactorItem = addFormFactorItem<SawtoothRippleLorentzItem>(parent);
489  formfactorItem->setLength(formfactor->length());
490  formfactorItem->setWidth(formfactor->width());
491  formfactorItem->setHeight(formfactor->height());
492  formfactorItem->setAsymmetry(formfactor->asymmetry());
493  } else if (const auto* formfactor = dynamic_cast<const Pyramid3*>(iFormFactor)) {
494  auto* formfactorItem = addFormFactorItem<Pyramid3Item>(parent);
495  formfactorItem->setBaseEdge(formfactor->baseEdge());
496  formfactorItem->setHeight(formfactor->height());
497  formfactorItem->setAlpha(Units::rad2deg(formfactor->alpha()));
498  } else if (const auto* formfactor = dynamic_cast<const TruncatedCube*>(iFormFactor)) {
499  auto* formfactorItem = addFormFactorItem<TruncatedCubeItem>(parent);
500  formfactorItem->setLength(formfactor->length());
501  formfactorItem->setRemovedLength(formfactor->removedLength());
502  } else if (const auto* formfactor = dynamic_cast<const TruncatedSphere*>(iFormFactor)) {
503  auto* formfactorItem = addFormFactorItem<TruncatedSphereItem>(parent);
504  formfactorItem->setRadius(formfactor->radius());
505  formfactorItem->setHeight(formfactor->height());
506  formfactorItem->setRemovedTop(formfactor->removedTop());
507  } else if (const auto* formfactor = dynamic_cast<const TruncatedSpheroid*>(iFormFactor)) {
508  auto* formfactorItem = addFormFactorItem<TruncatedSpheroidItem>(parent);
509  formfactorItem->setRadius(formfactor->radius());
510  formfactorItem->setHeight(formfactor->height());
511  formfactorItem->setHeightFlattening(formfactor->heightFlattening());
512  formfactorItem->setRemovedTop(formfactor->removedTop());
513  } else if (const auto* formfactor = dynamic_cast<const CantellatedCube*>(iFormFactor)) {
514  auto* formfactorItem = addFormFactorItem<CantellatedCubeItem>(parent);
515  formfactorItem->setLength(formfactor->length());
516  formfactorItem->setRemovedLength(formfactor->removedLength());
517  } else if (const auto* formfactor = dynamic_cast<const HorizontalCylinder*>(iFormFactor)) {
518  auto* formfactorItem = addFormFactorItem<HorizontalCylinderItem>(parent);
519  formfactorItem->setRadius(formfactor->radius());
520  formfactorItem->setLength(formfactor->length());
521  formfactorItem->setSliceBottom(formfactor->slice_bottom());
522  formfactorItem->setSliceTop(formfactor->slice_top());
523  } else if (const auto* formfactor = dynamic_cast<const PlatonicOctahedron*>(iFormFactor)) {
524  auto* formfactorItem = addFormFactorItem<PlatonicOctahedronItem>(parent);
525  formfactorItem->setEdge(formfactor->edge());
526  } else if (const auto* formfactor = dynamic_cast<const PlatonicTetrahedron*>(iFormFactor)) {
527  auto* formfactorItem = addFormFactorItem<PlatonicTetrahedronItem>(parent);
528  formfactorItem->setEdge(formfactor->edge());
529  } else
530  ASSERT(false);
531 }
532 
533 MaterialItem* findMaterialItem(MaterialItems& matItems, const ISampleNode* node)
534 {
535  const Material* material = node->material();
536 
537  QString materialName = QString::fromStdString(material->materialName());
538 
539  MaterialItem* materialItem = matItems.materialFromName(materialName);
540  if (materialItem)
541  return materialItem;
542 
543  complex_t material_data = material->materialData();
544  if (material->typeID() == MATERIAL_TYPES::RefractiveMaterial) {
545  materialItem = matItems.addRefractiveMaterial(materialName, material_data.real(),
546  material_data.imag());
547  } else if (material->typeID() == MATERIAL_TYPES::MaterialBySLD) {
548  materialItem =
549  matItems.addSLDMaterial(materialName, material_data.real(), material_data.imag());
550  } else
551  ASSERT(0);
552 
553  materialItem->setMagnetization(material->magnetization());
554 
555  return materialItem;
556 }
557 
558 void copyParticleItem(ParticleItem* particleItem, MaterialItems& matItems, const Particle* particle)
559 {
560  particleItem->setAbundance(particle->abundance());
561  particleItem->setPosition(particle->particlePosition());
562  particleItem->setMaterial(findMaterialItem(matItems, particle));
563  setRotation(particleItem, particle->rotation());
564  setFormFactor(particleItem, particle->formfactor_at_bottom());
565 }
566 
567 void copyParticle(const IParticle* iparticle, MaterialItems& matItems,
568  std::function<void(ItemWithParticles*)> addToParent)
569 {
570  if (const auto* particle = dynamic_cast<const Particle*>(iparticle)) {
571  auto* particle_item = new ParticleItem(&matItems);
572  copyParticleItem(particle_item, matItems, particle);
573  addToParent(particle_item);
574  } else if (const auto* coreshell = dynamic_cast<const ParticleCoreShell*>(iparticle)) {
575  if (!coreshell->coreParticle())
576  throw std::runtime_error("core/shell particle has no core particle.");
577  if (!coreshell->shellParticle())
578  throw std::runtime_error("core/shell particle has no shell particle.");
579 
580  auto* coreShellItem = new ParticleCoreShellItem(&matItems);
581  coreShellItem->setAbundance(coreshell->abundance());
582  coreShellItem->setPosition(coreshell->particlePosition());
583  setRotation(coreShellItem, coreshell->rotation());
584 
585  if (const Particle* p = coreshell->coreParticle()) {
586  coreShellItem->createCore(&matItems);
587  copyParticleItem(coreShellItem->core(), matItems, p);
588  }
589  if (const Particle* p = coreshell->shellParticle()) {
590  coreShellItem->createShell(&matItems);
591  copyParticleItem(coreShellItem->shell(), matItems, p);
592  }
593 
594  addToParent(coreShellItem);
595  } else if (const auto* meso = dynamic_cast<const MesoCrystal*>(iparticle)) {
596  if (!meso->particleStructure().basis())
597  throw std::runtime_error("Meso crystal has no basis.");
598 
599  auto* mesoItem = new MesoCrystalItem(&matItems);
600  mesoItem->setAbundance(meso->abundance());
601  mesoItem->setPosition(meso->particlePosition());
602  setFormFactor(mesoItem, meso->outerShape());
603  setRotation(mesoItem, meso->rotation());
604 
605  const Lattice3D* lattice = meso->particleStructure().lattice();
606  mesoItem->setRawDataVectorA(lattice->basisVectorA());
607  mesoItem->setRawDataVectorB(lattice->basisVectorB());
608  mesoItem->setRawDataVectorC(lattice->basisVectorC());
609  addToParent(mesoItem);
610 
611  copyParticle(meso->particleStructure().basis(), matItems,
612  [=](ItemWithParticles* p) { mesoItem->setBasis(p); });
613 
614  } else if (const auto* particleComposition =
615  dynamic_cast<const ParticleComposition*>(iparticle)) {
616  auto* particleCompositionItem = new ParticleCompositionItem(&matItems);
617 
618  particleCompositionItem->setAbundance(particleComposition->abundance());
619  particleCompositionItem->setPosition(particleComposition->particlePosition());
620  setRotation(particleCompositionItem, particleComposition->rotation());
621  addToParent(particleCompositionItem);
622 
623  for (const auto* p : particleComposition->particles())
624  copyParticle(p, matItems,
625  [=](ItemWithParticles* p) { particleCompositionItem->addParticle(p); });
626  }
627 }
628 
629 } // namespace
630 
631 
633 
634 MultiLayerItem* itemizeSample(const MultiLayer& sample, const QString& nodeName)
635 {
636  auto* result = new MultiLayerItem();
637  result->setSampleName(nodeName.isEmpty() ? QString::fromStdString(sample.sampleName())
638  : nodeName);
639  result->crossCorrLength().set(sample.crossCorrLength());
640  result->setExternalField(sample.externalField());
641 
642  MaterialItems& matItems = result->materialItems();
643 
644  // iterate over layers
645  for (size_t layerIndex = 0; layerIndex < sample.numberOfLayers(); layerIndex++) {
646  const auto* layer = sample.layer(layerIndex);
647 
648  const LayerInterface* top_interface =
649  layerIndex == 0 ? nullptr : sample.layerInterface(layerIndex - 1);
650 
651  auto* layerItem = result->addLayer();
652  layerItem->setMaterial(findMaterialItem(matItems, layer));
653  layerItem->setIsTopLayer(layerIndex == 0);
654  layerItem->setIsBottomLayer(layerIndex == sample.numberOfLayers() - 1);
655 
656  setLayerItem(layerItem, layer, top_interface);
657 
658  // iterate over particle layouts
659  for (const auto* layout : layer->layouts()) {
660  auto* layoutItem = layerItem->addLayout();
661  layoutItem->ownDensity().set(layout->totalParticleSurfaceDensity());
662  layoutItem->weight().set(layout->weight());
663  setInterference(layoutItem, layout->interferenceFunction());
664 
665  // create particles/particle compositions
666  for (const IParticle* particle : layout->particles())
667  copyParticle(particle, matItems,
668  [=](ItemWithParticles* p) { layoutItem->addParticle(p); });
669  }
670  }
671 
672  return result;
673 }
674 
675 } // namespace GUI::Transform::FromCore
Defines class DoubleDescriptor.
Defines error class.
Defines class GUISampleBuilder.
Defines class LayerItem.
Defines class MaterialItem.
Defines class MaterialItems.
Defines class MesoCrystalItem.
Defines class MultiLayerItem.
Defines class ParticleCompositionItem.
Defines class ParticleCoreShellItem.
Defines class ParticleItem.
Defines class ParticleLayoutItem.
function< void(double)> set
function to set the value
Definition: Error.h:21
DoubleDescriptor length() const
void setDecayFunction(Profile1DItem *p)
DoubleDescriptor rotationAngle() const
void setLatticeType(Lattice2DItem *p)
void setXiIntegration(bool xiIntegration)
void setDecayFunctionType(Profile2DItem *p)
void setPDF2Type(Profile2DItem *p)
void setDampingLength(double dampingLength)
void setPDF1Type(Profile2DItem *p)
void setDomainSize1(unsigned int domain_size1)
void setDomainSize2(unsigned int domain_size2)
DoubleDescriptor density() const
DoubleDescriptor radius() const
DoubleDescriptor positionVariance() const
DoubleDescriptor dampingLength() const
DoubleDescriptor domainSize() const
DoubleDescriptor peakDistance() const
void setMaterial(const MaterialItem *materialItem)
Set the material this item shall use. Stores the identifier, not the pointer!
void setPosition(const R3 &position)
void setAbundance(double abundance)
void setRotation(RotationItem *p)
nullptr is allowed and sets to "no rotation"
DoubleDescriptor lateralCorrelationLength() const
DoubleDescriptor sigma() const
DoubleDescriptor hurst() const
void setIsTopLayer(bool b)
Definition: LayerItem.cpp:163
void clearRoughness()
Definition: LayerItem.cpp:126
UIntDescriptor numSlices() const
Definition: LayerItem.cpp:131
ParticleLayoutItem * addLayout()
Definition: LayerItem.cpp:141
void setIsBottomLayer(bool b)
Definition: LayerItem.cpp:173
void setBasicRoughness()
Definition: LayerItem.cpp:121
DoubleDescriptor thickness() const
Definition: LayerItem.cpp:97
SelectionDescriptor< LayerBasicRoughnessItem * > roughness()
Definition: LayerItem.cpp:102
void setMagnetization(const R3 &magnetization)
MaterialItem * addRefractiveMaterial(const QString &name, double delta, double beta)
MaterialItem * addSLDMaterial(const QString &name, double sld, double abs_term)
const QVector< MaterialItem * > & materialItems() const
MaterialItem * materialFromName(const QString &name) const
DoubleDescriptor ownDensity() const
The density value which belonging only to the layout.
void addParticle(ItemWithParticles *particle)
DoubleDescriptor weight() const
void setInterference(InterferenceItem *interference)
void setOmegaX(double omega_x)
void setOmegaY(double omega_y)
void setGamma(double gamma)
void setEta(double eta)
DoubleDescriptor eta() const
function< void(uint)> set
function to set the value
Contains set of methods to populate GUI models with content from domain.
MultiLayerItem * itemizeSample(const MultiLayer &sample, const QString &nodeName)
Builds GUI sample structure from a domain sample structure.