BornAgain  1.19.79
Open-source research software to simulate and fit neutron and x-ray reflectometry and grazing-incidence small-angle scattering
Compute::Slicing Namespace Reference

Functions

ParticleInSlice createParticleInSlice (const IParticle *particle, const ZLimits &)
 
std::vector< ZLimitsparticleRegions (const MultiLayer &sample, bool use_slicing)
 Calculate z-admixtures occupied by particles. More...
 
ZLimits zSpan (const IParticle *particle)
 

Function Documentation

◆ createParticleInSlice()

ParticleInSlice Compute::Slicing::createParticleInSlice ( const IParticle particle,
const ZLimits limits 
)

Definition at line 251 of file Slicer.cpp.

253 {
254  if (const auto* p = dynamic_cast<const Particle*>(particle)) {
255  ASSERT(p->formfactor_at_bottom());
256  std::unique_ptr<ReParticle> particleSlice(createParticleSlice(
257  p->formfactor_at_bottom(), limits, p->rotation(), p->particlePosition()));
258  if (!particleSlice)
259  return {};
260  double volume = particleSlice->volume();
261  Material transformed_material(
262  p->rotation() ? p->material()->rotatedMaterial(p->rotation()->rotMatrix())
263  : *p->material());
264  particleSlice->setMaterial(transformed_material);
265  return {std::move(particleSlice), {{{volume, transformed_material}}}};
266 
267  } else if (const auto* p = dynamic_cast<const ParticleCoreShell*>(particle)) {
268  const Particle* core = p->coreParticle();
269  const Particle* shell = p->shellParticle();
270  ASSERT(core && shell);
271 
272  // core
273  std::unique_ptr<Particle> P_core(core->clone());
274  if (p->rotation())
275  P_core->rotate(*p->rotation());
276  P_core->translate(p->particlePosition());
277  ParticleInSlice sliced_core = createParticleInSlice(P_core.get(), limits);
278 
279  // shell
280  std::unique_ptr<Particle> P_shell(shell->clone());
281  if (p->rotation())
282  P_shell->rotate(*p->rotation());
283  P_shell->translate(p->particlePosition());
284  ParticleInSlice sliced_shell = createParticleInSlice(P_shell.get(), limits);
285  if (!sliced_shell.particleSlice)
286  return {};
287 
288  ParticleInSlice result;
289  // if core out of limits, return sliced shell
290  if (!sliced_core.particleSlice) {
291  result.particleSlice.reset(std::move(sliced_shell.particleSlice.get()));
292  result.admixtures.push_back(sliced_shell.admixtures.back());
293  return result;
294  }
295 
296  // set core ambient material
297  if (sliced_shell.admixtures.size() != 1)
298  return {};
299  auto shell_material = sliced_shell.admixtures[0].material;
300  sliced_core.particleSlice->setAmbientMaterial(shell_material);
301 
302  // construct sliced particle
303  sliced_shell.admixtures.back().fraction -= sliced_core.admixtures.back().fraction;
304  result.particleSlice.reset(new ReCoreShell(sliced_core.particleSlice.release(),
305  sliced_shell.particleSlice.release()));
306  result.admixtures.push_back(sliced_core.admixtures.back());
307  result.admixtures.push_back(sliced_shell.admixtures.back());
308 
309  return result;
310 
311  } else if (dynamic_cast<const ParticleComposition*>(particle)) {
312  throw std::runtime_error("ParticleComposition does not yet support slicing");
313 
314  } else if (const auto* p = dynamic_cast<const MesoCrystal*>(particle)) {
315  const Crystal* crystal = &p->particleStructure();
316  const IFormFactor* meso_formfactor = p->outerShape();
317  ASSERT(crystal && meso_formfactor);
318 
319  double unit_cell_volume = crystal->lattice()->unitCellVolume();
320  if (unit_cell_volume <= 0)
321  return {};
322 
323  ParticleInSlice result;
324 
325  std::unique_ptr<ReParticle> new_shape(
326  createParticleSlice(meso_formfactor, limits, p->rotation(), p->particlePosition()));
327 
328  const std::unique_ptr<Crystal> new_crystal(
329  crystal->transformed(p->rotation(), p->particlePosition()));
330 
331  const std::unique_ptr<IReParticle> new_basis(processBasis(new_crystal->basis()));
332 
333  result.particleSlice.reset(new ReMesocrystal(*new_crystal->lattice(), *new_basis,
334  *new_shape, new_crystal->position_variance()));
335 
336  Admixtures& regions = result.admixtures;
337  ASSERT(regions.empty());
338  for (const auto& particle : crystal->basis()->decompose()) {
339  ParticleInSlice pis = createParticleInSlice(particle.get(), {});
340  regions.insert(regions.end(), pis.admixtures.begin(), pis.admixtures.end());
341  }
342  for (auto& region : regions)
343  region.fraction *= meso_formfactor->volume() / unit_cell_volume;
344 
345  return result;
346 
347  } else
348  ASSERT(0);
349 }
#define ASSERT(condition)
Definition: Assert.h:45
The list of material admixtures to a slice.
Definition: Admixtures.h:39
A crystal structure, defined by a Bravais lattice, a basis, and a position variance.
Definition: Crystal.h:34
Crystal * transformed(const IRotation *rotation, const R3 &translation) const
Definition: Crystal.cpp:46
const IParticle * basis() const
Definition: Crystal.h:47
const Lattice3D * lattice() const
Definition: Crystal.h:48
Abstract base class for Born form factors.
Definition: IFormFactor.h:36
virtual double volume() const
Definition: IFormFactor.cpp:83
virtual std::vector< std::unique_ptr< IParticle > > decompose() const
Decompose in constituent IParticle objects.
Definition: IParticle.cpp:52
double unitCellVolume() const
Returns the volume of the unit cell.
Definition: Lattice3D.cpp:56
A wrapper for underlying material implementation.
Definition: Material.h:35
A particle with a crystalline inner structure, made of smaller particles, and an outer shape describe...
Definition: MesoCrystal.h:27
A composition of particles at fixed positions.
A particle with a core/shell geometry.
A particle with a form factor and refractive index.
Definition: Particle.h:25
Particle * clone() const override
Returns a clone of this ISampleNode object.
Definition: Particle.cpp:34
A reprocessed core shell particle.
Definition: ReCoreShell.h:29
A reprocessed MesoCrystal.
Definition: ReMesocrystal.h:29
ParticleInSlice createParticleInSlice(const IParticle *particle, const ZLimits &)
Definition: Slicer.cpp:251
Struct that contains information on a sliced particle. This information is needed for evaluating the ...
Admixtures admixtures
std::unique_ptr< IReParticle > particleSlice

References ParticleInSlice::admixtures, ASSERT, Crystal::basis(), Particle::clone(), IParticle::decompose(), Crystal::lattice(), ParticleInSlice::particleSlice, Crystal::transformed(), Lattice3D::unitCellVolume(), and IFormFactor::volume().

Referenced by zSpan().

Here is the call graph for this function:

◆ particleRegions()

std::vector< ZLimits > Compute::Slicing::particleRegions ( const MultiLayer sample,
bool  use_slicing 
)

Calculate z-admixtures occupied by particles.

Definition at line 157 of file ParticleRegions.cpp.

158 {
159  const std::vector<double> bottom_coords = bottomLayerCoordinates(sample);
160  LayerFillLimits layer_fill_limits(bottom_coords);
161  if (use_slicing) {
162  for (size_t i = 0; i < sample.numberOfLayers(); ++i) {
163  const Layer* layer = sample.layer(i);
164  const double offset = (i == 0) ? 0 : bottom_coords[i - 1];
165  for (const auto* layout : layer->layouts())
166  for (const IParticle* particle : layout->particles())
167  layer_fill_limits.update(Compute::Slicing::zSpan(particle), offset);
168  }
169  }
170  return layer_fill_limits.layerZLimits();
171 }
Abstract base class for Particle, ParticleComposition, ParticleCoreShell, MesoCrystal....
Definition: IParticle.h:31
A layer in a MultiLayer sample.
Definition: Layer.h:26
std::vector< const ParticleLayout * > layouts() const
Definition: Layer.cpp:54
const Layer * layer(size_t i_layer) const
Returns layer with given index.
Definition: MultiLayer.cpp:91
size_t numberOfLayers() const
Definition: MultiLayer.h:51
ZLimits zSpan(const IParticle *particle)
Definition: Slicer.cpp:351

References MultiLayer::layer(), Layer::layouts(), MultiLayer::numberOfLayers(), and zSpan().

Here is the call graph for this function:

◆ zSpan()

ZLimits Compute::Slicing::zSpan ( const IParticle particle)

Definition at line 351 of file Slicer.cpp.

352 {
353  if (const auto* p = dynamic_cast<const ParticleComposition*>(particle)) {
354  const auto subparticles = p->decompose();
355  ASSERT(subparticles.size() > 0);
356  ZLimits result = zSpan(subparticles[0].get());
357  for (const auto& subparticle : subparticles)
358  result = ZLimits::enclosingInterval(result, zSpan(subparticle.get()));
359  return result;
360  }
361  const ParticleInSlice pis = createParticleInSlice(particle, ZLimits{});
362  const double bot = pis.particleSlice->bottomZ(nullptr);
363  const double top = pis.particleSlice->topZ(nullptr);
364  return {bot, top};
365 }
An interval. Limits are of type double, and may be infinite. Used for the z-coordinate,...
Definition: ZLimits.h:32
static ZLimits enclosingInterval(const ZLimits &left, const ZLimits &right)
Returns the union of two ZLimits (the minimal interval that contains both input intervals).
Definition: ZLimits.cpp:37

References ASSERT, createParticleInSlice(), ZLimits::enclosingInterval(), and ParticleInSlice::particleSlice.

Referenced by particleRegions().

Here is the call graph for this function: