1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
|
// ************************************************************************************************
//
// BornAgain: simulate and fit reflection and scattering
//
//! @file Resample/Particle/ReParticle.cpp
//! @brief Implements class interface ReParticle.
//!
//! @homepage http://www.bornagainproject.org
//! @license GNU General Public License v3 or higher (see COPYING)
//! @copyright Forschungszentrum Jülich GmbH 2018
//! @authors Scientific Computing Group at MLZ (see CITATION, AUTHORS)
//
// ************************************************************************************************
#include "Resample/Particle/ReParticle.h"
#include "Base/Type/Span.h"
#include "Base/Util/Assert.h"
#include "Base/Vector/WavevectorInfo.h" // debug
#include "Sample/Material/Material.h"
#include "Sample/Material/MaterialFactoryFuncs.h"
#include "Sample/Particle/IFormfactor.h"
#include "Sample/Scattering/Rotations.h"
ReParticle::ReParticle(const std::optional<size_t>& i_layer, const IFormfactor* ff,
const Material* material, const Material* ambient_material,
const R3* position, const RotMatrix* rotMatrix)
: IReParticle(i_layer)
, m_ff(ff)
, m_material(material)
, m_ambient_material(ambient_material)
, m_position(position)
, m_rot_matrix(rotMatrix)
{
}
ReParticle::ReParticle(const IFormfactor* ff, const R3* position, const RotMatrix* rot)
: ReParticle({}, ff, nullptr, nullptr, position, rot)
{
}
ReParticle::~ReParticle() = default;
ReParticle* ReParticle::clone() const
{
return new ReParticle(i_layer(), m_ff->clone(),
m_material ? new Material(*m_material) : nullptr,
m_ambient_material ? new Material(*m_ambient_material) : nullptr,
m_position ? new R3(*m_position) : nullptr,
m_rot_matrix ? new RotMatrix(*m_rot_matrix) : nullptr);
}
void ReParticle::setMaterial(const Material& material)
{
m_material = std::make_unique<Material>(material);
}
void ReParticle::setAmbientMaterial(const Material& ambient_material)
{
m_ambient_material = std::make_unique<Material>(ambient_material);
}
double ReParticle::volume() const
{
return m_ff->volume();
}
double ReParticle::radialExtension() const
{
return m_ff->radialExtension();
}
complex_t ReParticle::theFF(const WavevectorInfo& wavevectors) const
{
WavevectorInfo wavevectors2 =
m_rot_matrix ? wavevectors.transformed(m_rot_matrix->Inverse()) : wavevectors;
complex_t result = m_ff->theFF(wavevectors2);
if (m_material && m_ambient_material)
result = (m_material->scalarSubtrSLD(wavevectors2)
- m_ambient_material->scalarSubtrSLD(wavevectors2))
* result;
return result * phaseFactor(wavevectors, m_position.get());
}
SpinMatrix ReParticle::thePolFF(const WavevectorInfo& wavevectors) const
{
WavevectorInfo wavevectors2 =
m_rot_matrix ? wavevectors.transformed(m_rot_matrix->Inverse()) : wavevectors;
SpinMatrix result = m_ff->thePolFF(wavevectors2);
if (m_material && m_ambient_material) {
// the conjugated linear part of time reversal operator T
// (T=UK with K complex conjugate operator and U is linear)
SpinMatrix time_reverse_conj(0, 1, -1, 0);
// the interaction and time reversal taken together:
SpinMatrix V_eff = time_reverse_conj
* (m_material->polarizedSubtrSLD(wavevectors2)
- m_ambient_material->polarizedSubtrSLD(wavevectors2));
result *= V_eff;
}
return result * phaseFactor(wavevectors, m_position.get());
}
Span ReParticle::zSpan() const
{
RotMatrix transform = m_rot_matrix ? *m_rot_matrix : RotMatrix();
std::unique_ptr<const IRotation> total_rotation(IRotation::createRotation(transform));
Span span = m_ff->spanZ(total_rotation.get());
if (m_position)
return span + m_position->z();
return span;
}
bool ReParticle::contains(const R3& position) const
{
return m_ff->contains(position);
}
bool ReParticle::consideredEqualTo(const IReParticle& ire) const
{
if (const auto* re = dynamic_cast<const ReParticle*>(&ire)) {
bool same_material = (!m_material && !re->material())
|| (m_material && re->material() && (*m_material == *re->material()));
bool same_ambient = (!m_ambient_material && !re->ambientMaterial())
|| (m_ambient_material && re->ambientMaterial()
&& (*m_ambient_material == *re->ambientMaterial()));
bool same_rotation =
(!m_rot_matrix && !re->rotMatrix())
|| (m_rot_matrix && re->rotMatrix() && (*m_rot_matrix == *re->rotMatrix()));
bool same_ff = (m_ff && re->ff() && m_ff->isEqualTo(re->ff()));
// translated position is not compared here, this is intentional
return IReParticle::consideredEqualTo(ire) && same_ff && same_material && same_ambient
&& same_rotation;
}
return false;
}
|