BornAgain  1.19.79
Open-source research software to simulate and fit neutron and x-ray reflectometry and grazing-incidence small-angle scattering
SampleToPython.cpp
Go to the documentation of this file.
1 // ************************************************************************************************
2 //
3 // BornAgain: simulate and fit reflection and scattering
4 //
5 //! @file Sim/Export/SampleToPython.cpp
6 //! @brief Implements class SampleToPython.
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/Py/PyFmt.h"
17 #include "Base/Util/Assert.h"
18 #include "Base/Vector/RotMatrix.h"
19 #include "Param/Node/NodeUtils.h"
34 #include "Sim/Export/PyFmt2.h"
35 #include <iomanip>
36 #include <map>
37 #include <memory>
38 #include <set>
39 
40 using Py::Fmt::indent;
41 
42 static const std::map<int, char> axisChar{{0, 'X'}, {1, 'Y'}, {2, 'Z'}};
43 
44 namespace {
45 
46 void setRotationInformation(const IParticle* particle, std::string name, std::ostringstream& result)
47 {
48  if (!particle->rotation())
49  return;
50  const RotMatrix matrix = particle->rotation()->rotMatrix();
51  // Identity matrix?
52  if (matrix.isIdentity())
53  return;
54  // Rotation around coordinate axis?
55  for (int iAxis = 0; iAxis < 3; ++iAxis) {
56  std::optional<double> angle = matrix.angleAroundCoordAxis(iAxis);
57  if (angle) {
58  result << indent() << name << "_rotation = ba.Rotation" << axisChar.at(iAxis) << "("
59  << Py::Fmt::printDegrees(angle.value()) << ")\n";
60  result << indent() << name << ".setRotation(" << name << "_rotation)\n";
61  return;
62  }
63  }
64  // Generic rotation.
65  auto angles = matrix.zxzEulerAngles();
66  result << indent() << name << "_rotation = ba.RotationEuler("
67  << Py::Fmt::printDegrees(angles[0]) << ", " << Py::Fmt::printDegrees(angles[1]) << ", "
68  << Py::Fmt::printDegrees(angles[2]) << ")\n";
69  result << indent() << name << ".setRotation(" << name << "_rotation)\n";
70 }
71 
72 void setPositionInformation(const IParticle* particle, std::string name, std::ostringstream& result)
73 {
74  R3 pos = particle->particlePosition();
75  if (pos == R3())
76  return;
77 
78  result << indent() << name << "_position = R3(" << Py::Fmt::printNm(pos.x()) << ", "
79  << Py::Fmt::printNm(pos.y()) << ", " << Py::Fmt::printNm(pos.z()) << ")\n";
80  result << indent() << name << ".setParticlePosition(" << name << "_position)\n";
81 }
82 
83 } // namespace
84 
85 // ************************************************************************************************
86 // class SampleToPython
87 // ************************************************************************************************
88 
89 std::string SampleToPython::sampleCode(const MultiLayer& sample)
90 {
91  initLabels(sample);
92  return defineGetSample();
93 }
94 
96 {
97  m_objs = std::make_unique<ComponentKeyHandler>();
98  m_materials = std::make_unique<MaterialKeyHandler>();
99 
100  for (const auto* x : sample.containedMaterials())
101  m_materials->insertMaterial(x);
102 
103  m_objs->insertModel("sample", &sample);
104  for (const auto* x : NodeUtils::AllDescendantsOfType<Layer>(sample))
105  m_objs->insertModel("layer", x);
106  for (const auto* x : NodeUtils::AllDescendantsOfType<LayerRoughness>(sample))
107  m_objs->insertModel("roughness", x);
108  for (const auto* x : NodeUtils::AllDescendantsOfType<ParticleLayout>(sample))
109  m_objs->insertModel("layout", x);
110  for (const auto* x : NodeUtils::AllDescendantsOfType<IFormFactor>(sample))
111  m_objs->insertModel("ff", x);
112  for (const auto* x : NodeUtils::AllDescendantsOfType<IInterference>(sample))
113  m_objs->insertModel("iff", x);
114  for (const auto* x : NodeUtils::AllDescendantsOfType<Particle>(sample))
115  m_objs->insertModel("particle", x);
116  for (const auto* x : NodeUtils::AllDescendantsOfType<ParticleComposition>(sample))
117  m_objs->insertModel("particle", x);
118  for (const auto* x : NodeUtils::AllDescendantsOfType<ParticleCoreShell>(sample))
119  m_objs->insertModel("particle", x);
120  for (const auto* x : NodeUtils::AllDescendantsOfType<MesoCrystal>(sample))
121  m_objs->insertModel("particle", x);
122  for (const auto* x : NodeUtils::AllDescendantsOfType<Lattice2D>(sample))
123  m_objs->insertModel("lattice", x);
124  for (const auto* x : NodeUtils::AllDescendantsOfType<Lattice3D>(sample))
125  m_objs->insertModel("lattice", x);
126  for (const auto* x : NodeUtils::AllDescendantsOfType<Crystal>(sample))
127  m_objs->insertModel("crystal", x);
128 }
129 
131 
133 
135 {
136  return "def get_sample():\n" + defineMaterials() + defineFormFactors() + defineParticles()
140  + "\n\n";
141 }
142 
143 const std::map<MATERIAL_TYPES, std::string> factory_names{
144  {MATERIAL_TYPES::RefractiveMaterial, "RefractiveMaterial"},
145  {MATERIAL_TYPES::MaterialBySLD, "MaterialBySLD"}};
146 
148 {
149  const auto themap = m_materials->materialMap();
150  if (themap.empty())
151  return "";
152  std::ostringstream result;
153  result << std::setprecision(12);
154  result << indent() << "# Define materials\n";
155  std::set<std::string> visitedMaterials;
156  for (const auto& it : themap) {
157  const std::string& key = it.first;
158  if (visitedMaterials.find(key) != visitedMaterials.end())
159  continue;
160  visitedMaterials.insert(key);
161  const Material* p_material = it.second;
162  const auto factory_name = factory_names.find(p_material->typeID());
163  if (factory_name == factory_names.cend())
164  throw std::runtime_error(
165  "Error in Py::Export::defineMaterials(): unknown material type");
166  const complex_t& material_data = p_material->materialData();
167  if (p_material->isScalarMaterial()) {
168  result << indent() << m_materials->mat2key(p_material) << " = ba."
169  << factory_name->second << "(\"" << p_material->materialName() << "\", "
170  << Py::Fmt::printDouble(material_data.real()) << ", "
171  << Py::Fmt::printDouble(material_data.imag()) << ")\n";
172  } else {
173  R3 magnetic_field = p_material->magnetization();
174  result << indent() << "magnetic_field = R3(" << magnetic_field.x() << ", "
175  << magnetic_field.y() << ", " << magnetic_field.z() << ")\n";
176  result << indent() << m_materials->mat2key(p_material) << " = ba."
177  << factory_name->second << "(\"" << p_material->materialName();
178  result << "\", " << Py::Fmt::printDouble(material_data.real()) << ", "
179  << Py::Fmt::printDouble(material_data.imag()) << ", "
180  << "magnetic_field)\n";
181  }
182  }
183  return result.str();
184 }
185 
186 std::string SampleToPython::defineLayers() const
187 {
188  std::vector<const Layer*> v = m_objs->objectsOfType<Layer>();
189  if (v.empty())
190  return "";
191  std::ostringstream result;
192  result << "\n" << indent() << "# Define layers\n";
193  result << std::setprecision(12);
194  for (const auto* s : v) {
195  const std::string& key = m_objs->obj2key(s);
196  result << indent() << key << " = ba.Layer(" << m_materials->mat2key(s->material());
197  if (s->thickness() != 0)
198  result << ", " << Py::Fmt::printNm(s->thickness());
199  result << ")\n";
200  if (s->numberOfSlices() != 1)
201  result << indent() << key << ".setNumberOfSlices(" << s->numberOfSlices() << ")\n";
202  for (const auto* layout : s->layouts())
203  result << indent() << key << ".addLayout(" << m_objs->obj2key(layout) << ")\n";
204  }
205  return result.str();
206 }
207 
209 {
210  std::vector<const LayerRoughness*> v = m_objs->objectsOfType<LayerRoughness>();
211  if (v.empty())
212  return "";
213  std::ostringstream result;
214  result << std::setprecision(12);
215  result << "\n" << indent() << "# Define roughness\n";
216  for (const auto* s : v) {
217  const std::string& key = m_objs->obj2key(s);
218  result << indent() << key << " = ba." << s->pythonConstructor() << "\n";
219  }
220  return result.str();
221 }
222 
224 {
225  std::vector<const IFormFactor*> formfactors = m_objs->objectsOfType<IFormFactor>();
226  if (formfactors.empty())
227  return "";
228  std::ostringstream result;
229  result << "\n" << indent() << "# Define form factors\n";
230  result << std::setprecision(12);
231  for (const auto* s : formfactors) {
232  const std::string& key = m_objs->obj2key(s);
233  result << indent() << key << " = ba." << s->pythonConstructor() << "\n";
234  }
235 
236  return result.str();
237 }
238 
240 {
241  std::vector<const IInterference*> v = m_objs->objectsOfType<IInterference>();
242  if (v.empty())
243  return "";
244  std::ostringstream result;
245  result << std::setprecision(12);
246  result << "\n" << indent() << "# Define interference functions\n";
247  for (const auto* s : v) {
248  const std::string& key = m_objs->obj2key(s);
249 
250  if (dynamic_cast<const InterferenceNone*>(s))
251  result << indent() << key << " = ba.InterferenceNone()\n";
252 
253  else if (const auto* iff = dynamic_cast<const Interference1DLattice*>(s)) {
254  result << indent() << key << " = ba.Interference1DLattice("
255  << Py::Fmt::printNm(iff->length()) << ", " << Py::Fmt::printDegrees(iff->xi())
256  << ")\n";
257 
258  const auto* pdf = NodeUtils::OnlyChildOfType<IProfile1D>(*iff);
259 
260  if (pdf->decayLength() != 0.0)
261  result << indent() << key << "_pdf = ba." << pdf->pythonConstructor() << "\n"
262  << indent() << key << ".setDecayFunction(" << key << "_pdf)\n";
263  } else if (const auto* iff = dynamic_cast<const InterferenceRadialParaCrystal*>(s)) {
264  result << indent() << key << " = ba.InterferenceRadialParaCrystal("
265  << Py::Fmt::printNm(iff->peakDistance()) << ", "
266  << Py::Fmt::printNm(iff->dampingLength()) << ")\n";
267 
268  if (iff->kappa() != 0.0)
269  result << indent() << key << ".setKappa(" << Py::Fmt::printDouble(iff->kappa())
270  << ")\n";
271 
272  if (iff->domainSize() != 0.0)
273  result << indent() << key << ".setDomainSize("
274  << Py::Fmt::printDouble(iff->domainSize()) << ")\n";
275 
276  const auto* pdf = NodeUtils::OnlyChildOfType<IProfile1D>(*iff);
277 
278  if (pdf->omega() != 0.0)
279  result << indent() << key << "_pdf = ba." << pdf->pythonConstructor() << "\n"
280  << indent() << key << ".setProbabilityDistribution(" << key << "_pdf)\n";
281  } else if (const auto* iff = dynamic_cast<const Interference2DLattice*>(s)) {
282  const auto* lattice = NodeUtils::OnlyChildOfType<Lattice2D>(*iff);
283 
284  result << indent() << key << " = ba.Interference2DLattice(" << m_objs->obj2key(lattice)
285  << ")\n";
286 
287  const auto* pdf = NodeUtils::OnlyChildOfType<IProfile2D>(*iff);
288 
289  result << indent() << key << "_pdf = ba." << pdf->pythonConstructor() << "\n"
290  << indent() << key << ".setDecayFunction(" << key << "_pdf)\n";
291 
292  if (iff->integrationOverXi())
293  result << indent() << key << ".setIntegrationOverXi(True)\n";
294  } else if (const auto* iff = dynamic_cast<const InterferenceFinite2DLattice*>(s)) {
295  const auto* lattice = NodeUtils::OnlyChildOfType<Lattice2D>(*iff);
296 
297  result << indent() << key << " = ba.InterferenceFinite2DLattice("
298  << m_objs->obj2key(lattice) << ", " << iff->numberUnitCells1() << ", "
299  << iff->numberUnitCells2() << ")\n";
300 
301  if (iff->integrationOverXi())
302  result << indent() << key << ".setIntegrationOverXi(True)\n";
303  } else if (const auto* iff = dynamic_cast<const Interference2DParaCrystal*>(s)) {
304  const auto* lattice = NodeUtils::OnlyChildOfType<Lattice2D>(*iff);
305  std::vector<double> domainSize = iff->domainSizes();
306 
307  result << indent() << key << " = ba.Interference2DParaCrystal("
308  << m_objs->obj2key(lattice) << ", " << Py::Fmt::printNm(iff->dampingLength())
309  << ", " << Py::Fmt::printNm(domainSize[0]) << ", "
310  << Py::Fmt::printNm(domainSize[1]) << ")\n";
311 
312  if (iff->integrationOverXi())
313  result << indent() << key << ".setIntegrationOverXi(True)\n";
314 
315  const auto pdf_vector = NodeUtils::ChildNodesOfType<IProfile2D>(*iff);
316  if (pdf_vector.size() != 2)
317  continue;
318  const IProfile2D* pdf = pdf_vector[0];
319 
320  result << indent() << key << "_pdf_1 = ba." << pdf->pythonConstructor() << "\n";
321 
322  pdf = pdf_vector[1];
323 
324  result << indent() << key << "_pdf_2 = ba." << pdf->pythonConstructor() << "\n";
325  result << indent() << key << ".setProbabilityDistributions(" << key << "_pdf_1, " << key
326  << "_pdf_2)\n";
327  } else if (const auto* lattice_hd = dynamic_cast<const InterferenceHardDisk*>(s)) {
328  result << indent() << key << " = ba.InterferenceHardDisk("
329  << Py::Fmt::printNm(lattice_hd->radius()) << ", "
330  << Py::Fmt::printDouble(lattice_hd->density()) << ")\n";
331  } else
332  ASSERT(0);
333 
334  if (s->positionVariance() > 0.0) {
335  result << indent() << key << ".setPositionVariance("
336  << Py::Fmt::printNm2(s->positionVariance()) << ")\n";
337  }
338  }
339  return result.str();
340 }
341 
343 {
344  std::vector<const ParticleLayout*> v = m_objs->objectsOfType<ParticleLayout>();
345  if (v.empty())
346  return "";
347  std::ostringstream result;
348  result << std::setprecision(12);
349  result << "\n" << indent() << "# Define particle layouts\n";
350  for (const auto* s : v) {
351  const std::string& key = m_objs->obj2key(s);
352  result << indent() << key << " = ba.ParticleLayout()\n";
353  const auto particles = NodeUtils::ChildNodesOfType<IParticle>(*s);
354  for (const auto* particle : particles) {
355  double abundance = particle->abundance();
356  result << indent() << key << ".addParticle(" << m_objs->obj2key(particle) << ", "
357  << Py::Fmt::printDouble(abundance) << ")\n";
358  }
359  if (const auto* iff = NodeUtils::OnlyChildOfType<IInterference>(*s))
360  result << indent() << key << ".setInterference(" << m_objs->obj2key(iff) << ")\n";
361  result << indent() << key << ".setWeight(" << s->weight() << ")\n";
362  result << indent() << key << ".setTotalParticleSurfaceDensity("
363  << s->totalParticleSurfaceDensity() << ")\n";
364  }
365  return result.str();
366 }
367 
369 {
370  std::vector<const Particle*> v = m_objs->objectsOfType<Particle>();
371  if (v.empty())
372  return "";
373  std::ostringstream result;
374  result << std::setprecision(12);
375  result << "\n" << indent() << "# Define particles\n";
376  for (const auto* s : v) {
377  const std::string& key = m_objs->obj2key(s);
378  const auto* ff = NodeUtils::OnlyChildOfType<IFormFactor>(*s);
379  ASSERT(ff);
380  result << indent() << key << " = ba.Particle(" << m_materials->mat2key(s->material())
381  << ", " << m_objs->obj2key(ff) << ")\n";
382  setRotationInformation(s, key, result);
383  setPositionInformation(s, key, result);
384  }
385  return result.str();
386 }
387 
389 {
390  std::vector<const ParticleCoreShell*> v = m_objs->objectsOfType<ParticleCoreShell>();
391  if (v.empty())
392  return "";
393  std::ostringstream result;
394  result << std::setprecision(12);
395  result << "\n" << indent() << "# Define core shell particles\n";
396  for (const auto* s : v) {
397  const std::string& key = m_objs->obj2key(s);
398  result << indent() << key << " = ba.ParticleCoreShell("
399  << m_objs->obj2key(s->shellParticle()) << ", " << m_objs->obj2key(s->coreParticle())
400  << ")\n";
401  setRotationInformation(s, key, result);
402  setPositionInformation(s, key, result);
403  }
404  return result.str();
405 }
406 
408 {
409  std::vector<const ParticleComposition*> v = m_objs->objectsOfType<ParticleComposition>();
410  if (v.empty())
411  return "";
412  std::ostringstream result;
413  result << std::setprecision(12);
414  result << "\n" << indent() << "# Define composition of particles at specific positions\n";
415  for (const auto* s : v) {
416  const std::string& key = m_objs->obj2key(s);
417  result << indent() << key << " = ba.ParticleComposition()\n";
418  const auto particle_list = NodeUtils::ChildNodesOfType<IParticle>(*s);
419  for (const auto* particle : particle_list)
420  result << indent() << key << ".addParticle(" << m_objs->obj2key(particle) << ")\n";
421  setRotationInformation(s, key, result);
422  setPositionInformation(s, key, result);
423  }
424  return result.str();
425 }
426 
428 {
429  std::vector<const MesoCrystal*> v = m_objs->objectsOfType<MesoCrystal>();
430  if (v.empty())
431  return "";
432  std::ostringstream result;
433  result << std::setprecision(12);
434  result << "\n" << indent() << "# Define mesocrystals\n";
435  for (const auto* s : v) {
436  const std::string& key = m_objs->obj2key(s);
437  const auto* crystal = NodeUtils::OnlyChildOfType<Crystal>(*s);
438  const auto* outer_shape = NodeUtils::OnlyChildOfType<IFormFactor>(*s);
439  if (!crystal || !outer_shape)
440  continue;
441  result << indent() << key << " = ba.MesoCrystal(";
442  result << m_objs->obj2key(crystal) << ", ";
443  result << m_objs->obj2key(outer_shape) << ")\n";
444  setRotationInformation(s, key, result);
445  setPositionInformation(s, key, result);
446  }
447  return result.str();
448 }
449 
451 {
452  std::vector<const Lattice2D*> v = m_objs->objectsOfType<Lattice2D>();
453  if (v.empty())
454  return "";
455  std::ostringstream result;
456  result << std::setprecision(12);
457  result << "\n" << indent() << "# Define 2D lattices\n";
458  for (const auto* s : v) {
459  const std::string& key = m_objs->obj2key(s);
460  result << indent() << key << " = ba.BasicLattice2D(\n";
461  result << indent() << indent() << Py::Fmt::printNm(s->length1()) << ", "
462  << Py::Fmt::printNm(s->length2()) << ", " << Py::Fmt::printDegrees(s->latticeAngle())
463  << ", " << Py::Fmt::printDegrees(s->rotationAngle()) << ")\n";
464  }
465  return result.str();
466 }
467 
469 {
470  std::vector<const Lattice3D*> v = m_objs->objectsOfType<Lattice3D>();
471  if (v.empty())
472  return "";
473  std::ostringstream result;
474  result << std::setprecision(12);
475  result << "\n" << indent() << "# Define 3D lattices\n";
476  for (const auto* s : v) {
477  const std::string& key = m_objs->obj2key(s);
478  R3 bas_a = s->basisVectorA();
479  R3 bas_b = s->basisVectorB();
480  R3 bas_c = s->basisVectorC();
481  result << indent() << key << " = ba.Lattice3D(\n";
482  result << indent() << indent() << "ba.R3(" << Py::Fmt::printNm(bas_a.x()) << ", "
483  << Py::Fmt::printNm(bas_a.y()) << ", " << Py::Fmt::printNm(bas_a.z()) << "),\n";
484  result << indent() << indent() << "ba.R3(" << Py::Fmt::printNm(bas_b.x()) << ", "
485  << Py::Fmt::printNm(bas_b.y()) << ", " << Py::Fmt::printNm(bas_b.z()) << "),\n";
486  result << indent() << indent() << "ba.R3(" << Py::Fmt::printNm(bas_c.x()) << ", "
487  << Py::Fmt::printNm(bas_c.y()) << ", " << Py::Fmt::printNm(bas_c.z()) << "))\n";
488  }
489  return result.str();
490 }
491 
493 {
494  std::vector<const Crystal*> v = m_objs->objectsOfType<Crystal>();
495  if (v.empty())
496  return "";
497  std::ostringstream result;
498  result << std::setprecision(12);
499  result << "\n" << indent() << "# Define crystals\n";
500  for (const auto* s : v) {
501  const std::string& key = m_objs->obj2key(s);
502  const auto* lattice = NodeUtils::OnlyChildOfType<Lattice3D>(*s);
503  const auto* basis = NodeUtils::OnlyChildOfType<IParticle>(*s);
504  if (!lattice || !basis)
505  continue;
506  result << indent() << key << " = ba.Crystal(";
507  result << m_objs->obj2key(basis) << ", ";
508  result << m_objs->obj2key(lattice) << ")\n";
509  }
510  return result.str();
511 }
512 
514 {
515  std::vector<const MultiLayer*> v = m_objs->objectsOfType<MultiLayer>();
516  if (v.empty())
517  return "";
518  std::ostringstream result;
519  result << std::setprecision(12);
520  ASSERT(v.size() == 1); // as long as there is exactly one sample, we shall use the singular
521  result << "\n" << indent() << "# Define sample\n";
522  for (const auto* s : v) {
523  const std::string& key = m_objs->obj2key(s);
524  result << indent() << key << " = ba.MultiLayer()\n";
525  double ccl = s->crossCorrLength();
526  if (ccl > 0.0)
527  result << indent() << key << ".setCrossCorrLength(" << ccl << ")\n";
528  auto external_field = s->externalField();
529  if (external_field.mag() > 0.0) {
530  std::string field_name = key + "_external_field";
531  result << indent() << field_name << " = R3("
532  << Py::Fmt::printScientificDouble(external_field.x()) << ", "
533  << Py::Fmt::printScientificDouble(external_field.y()) << ", "
534  << Py::Fmt::printScientificDouble(external_field.z()) << ")\n";
535  result << indent() << key << ".setExternalField(" << field_name << ")\n";
536  }
537  size_t numberOfLayers = s->numberOfLayers();
538  if (numberOfLayers) {
539  result << indent() << key << ".addLayer(" << m_objs->obj2key(s->layer(0)) << ")\n";
540 
541  size_t i_layer = 1;
542  while (i_layer != numberOfLayers) {
543  const LayerInterface* layerInterface = s->layerInterface(i_layer - 1);
544  if (const LayerRoughness* rough = layerInterface->roughness())
545  result << indent() << key << ".addLayerWithTopRoughness("
546  << m_objs->obj2key(s->layer(i_layer)) << ", " << m_objs->obj2key(rough)
547  << ")\n";
548  else
549  result << indent() << key << ".addLayer(" << m_objs->obj2key(s->layer(i_layer))
550  << ")\n";
551  i_layer++;
552  }
553  }
554  result << "\n" << indent() << "return " << key << "\n";
555  }
556  return result.str();
557 }
Defines the macro ASSERT.
#define ASSERT(condition)
Definition: Assert.h:45
Defines class ComponentKeyHandler.
Defines class Crystal.
Includes all interference function definitions.
Defines class LayerInterface.
Defines class LayerRoughness.
Defines class Layer.
Defines class MaterialKeyHandler.
Defines class MesoCrystal.
Defines class MultiLayer.
Defines collection of utility functions for INode.
Defines class ParticleComposition.
Defines ParticleCoreShell.
Defines class ParticleLayout.
Defines class Particle.
Defines namespace pyfmt2.
Defines namespace pyfmt.
Declares class RotMatrix.
Defines IRotation classes.
const std::map< MATERIAL_TYPES, std::string > factory_names
static const std::map< int, char > axisChar
Defines class SampleToPython.
A crystal structure, defined by a Bravais lattice, a basis, and a position variance.
Definition: Crystal.h:34
Abstract base class for Born form factors.
Definition: IFormFactor.h:36
Abstract base class of interference functions.
Definition: IInterference.h:24
Abstract base class for Particle, ParticleComposition, ParticleCoreShell, MesoCrystal....
Definition: IParticle.h:31
double abundance() const
Definition: IParticle.h:38
const IRotation * rotation() const
Returns rotation object.
Definition: IParticle.cpp:31
R3 particlePosition() const
Returns particle position.
Definition: IParticle.h:46
Interface for two-dimensional distributions in Fourier space.
Definition: Profiles2D.h:29
virtual std::string pythonConstructor() const
Creates the Python constructor of this class (or derived classes)
Definition: Profiles2D.cpp:34
virtual RotMatrix rotMatrix() const =0
Returns transformation.
std::vector< const Material * > containedMaterials() const
Returns set of unique materials contained in this ISampleNode.
Definition: ISampleNode.cpp:25
Interference function of a 1D lattice.
Interference function of a 2D lattice.
Interference function of a 2D paracrystal.
Interference function of a finite 2D lattice.
Percus-Yevick hard disk interference function.
Default interference function (i.e. absence of any interference).
Interference function of radial paracrystal.
A two-dimensional Bravais lattice.
Definition: Lattice2D.h:23
A Bravais lattice, characterized by three basis vectors, and optionally an ISelectionRule.
Definition: Lattice3D.h:30
Interface between two layers, possibly with roughness.
const LayerRoughness * roughness() const
Returns roughness of the interface.
A roughness of interface between two layers.
A layer in a MultiLayer sample.
Definition: Layer.h:26
A wrapper for underlying material implementation.
Definition: Material.h:35
R3 magnetization() const
Get the magnetization (in A/m)
Definition: Material.cpp:78
bool isScalarMaterial() const
Indicates whether the interaction with the material is scalar. This means that different polarization...
Definition: Material.cpp:58
std::string materialName() const
Returns the name of material.
Definition: Material.cpp:68
MATERIAL_TYPES typeID() const
Returns the type of underlying material implementation.
Definition: Material.cpp:73
complex_t materialData() const
Returns delta + i beta.
Definition: Material.cpp:83
A particle with a crystalline inner structure, made of smaller particles, and an outer shape describe...
Definition: MesoCrystal.h:27
Our sample model: a stack of layers one below the other.
Definition: MultiLayer.h:43
A composition of particles at fixed positions.
A particle with a core/shell geometry.
Decorator class that adds particles to ISampleNode objects.
A particle with a form factor and refractive index.
Definition: Particle.h:25
Rotation matrix in three dimensions. Represents group SO(3). Internal parameterization based on quate...
Definition: RotMatrix.h:25
bool isIdentity() const
Determine if the transformation is trivial (identity)
Definition: RotMatrix.cpp:111
std::optional< double > angleAroundCoordAxis(int iAxis) const
Definition: RotMatrix.cpp:131
std::array< double, 3 > zxzEulerAngles() const
Calculates the Euler angles corresponding to the rotation.
Definition: RotMatrix.cpp:53
std::string defineLayers() const
std::string defineGetSample() const
std::string defineFormFactors() const
std::string defineMaterials() const
std::string defineLattices3D() const
std::string defineMesoCrystals() const
std::string defineCrystals() const
std::string defineParticles() const
std::string defineParticleCompositions() const
std::unique_ptr< ComponentKeyHandler > m_objs
std::string defineLattices2D() const
std::string defineInterferences() const
std::string defineParticleLayouts() const
std::string defineCoreShellParticles() const
std::string sampleCode(const MultiLayer &sample)
void initLabels(const MultiLayer &sample)
std::string defineMultiLayers() const
std::string defineRoughnesses() const
std::unique_ptr< MaterialKeyHandler > m_materials
std::string printDegrees(double input)
Definition: PyFmt.cpp:116
std::string printDouble(double input)
Definition: PyFmt.cpp:46
std::string printScientificDouble(double input)
Definition: PyFmt.cpp:96
std::string printNm(double input)
Definition: PyFmt.cpp:79
std::string indent(size_t width)
Returns a string of blanks with given width. By default the width equals standard offset in python fi...
Definition: PyFmt.cpp:203
std::string printNm2(double input)
Definition: PyFmt.cpp:87